fontservices/textshaperplugin/IcuSource/layout/KernTable.cpp
changeset 0 1fb32624e06b
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2  * @(#)KernTable.cpp	1.1 04/10/13
       
     3  *
       
     4  * (C) Copyright IBM Corp. 2004-2005 - All Rights Reserved
       
     5  *
       
     6  */
       
     7 
       
     8 #include "KernTable.h"
       
     9 
       
    10 #include "LESwaps.h"
       
    11 
       
    12 #include <stdio.h>
       
    13 
       
    14 #define DEBUG 0
       
    15 
       
    16 U_NAMESPACE_BEGIN
       
    17 
       
    18 struct PairInfo {
       
    19   le_uint32 key;   // sigh, MSVC compiler gags on union here
       
    20   le_int16  value; // fword, kern value in funits
       
    21 };
       
    22 #define KERN_PAIRINFO_SIZE 6
       
    23 
       
    24 struct Subtable_0 {
       
    25   le_uint16 nPairs;
       
    26   le_uint16 searchRange;
       
    27   le_uint16 entrySelector;
       
    28   le_uint16 rangeShift;
       
    29 };
       
    30 #define KERN_SUBTABLE_0_HEADER_SIZE 8
       
    31 
       
    32 // Kern table version 0 only
       
    33 struct SubtableHeader {
       
    34   le_uint16 version;
       
    35   le_uint16 length;
       
    36   le_uint16 coverage;
       
    37 };
       
    38 #define KERN_SUBTABLE_HEADER_SIZE 6
       
    39 
       
    40 // Version 0 only, version 1 has different layout
       
    41 struct KernTableHeader {
       
    42   le_uint16 version;
       
    43   le_uint16 nTables;
       
    44 };
       
    45 #define KERN_TABLE_HEADER_SIZE 4
       
    46 
       
    47 #define COVERAGE_HORIZONTAL 0x1
       
    48 #define COVERAGE_MINIMUM 0x2
       
    49 #define COVERAGE_CROSS 0x4
       
    50 #define COVERAGE_OVERRIDE 0x8
       
    51 
       
    52 KernTable::KernTable(const LEFontInstance* font, const void* tableData) 
       
    53   : pairs(0), font(font)
       
    54 {
       
    55   const KernTableHeader* header = (const KernTableHeader*)tableData;
       
    56   if (header == 0) {
       
    57 #if DEBUG
       
    58     fprintf(stderr, "no kern data\n");
       
    59     fflush(stderr);
       
    60 #endif
       
    61     return;
       
    62   }
       
    63 
       
    64 #if DEBUG
       
    65   // dump first 32 bytes of header
       
    66   for (int i = 0; i < 64; ++i) {
       
    67     fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff);
       
    68     if (((i+1)&0xf) == 0) {
       
    69       fprintf(stderr, "\n");
       
    70     } else if (((i+1)&0x7) == 0) {
       
    71       fprintf(stderr, "  ");
       
    72     }
       
    73   }
       
    74   fflush(stderr);
       
    75 #endif
       
    76 
       
    77   if (header->version == 0 && SWAPW(header->nTables) > 0) {
       
    78     const SubtableHeader* subhead = (const SubtableHeader*)((char*)tableData + KERN_TABLE_HEADER_SIZE);
       
    79     if (subhead->version == 0) {
       
    80       coverage = SWAPW(subhead->coverage);
       
    81       if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning
       
    82 	const Subtable_0* table = (const Subtable_0*)((char*)subhead + KERN_SUBTABLE_HEADER_SIZE);
       
    83 	nPairs = SWAPW(table->nPairs);
       
    84 	searchRange = SWAPW(table->searchRange);
       
    85 	entrySelector = SWAPW(table->entrySelector);
       
    86 	rangeShift = SWAPW(table->rangeShift);
       
    87 	pairs = (const PairInfo*)((char*)table + KERN_SUBTABLE_0_HEADER_SIZE);
       
    88 
       
    89 #if DEBUG
       
    90 	fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs);
       
    91 	fprintf(stderr, "  searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift);
       
    92 	fflush(stderr);
       
    93 
       
    94 	{
       
    95 	  // dump part of the pair list
       
    96 	  char ids[256];
       
    97 	  for (int i = 256; --i >= 0;) {
       
    98 	    LEGlyphID id = font->mapCharToGlyph(i);
       
    99 	    if (id < 256) {
       
   100 	      ids[id] = (char)i;
       
   101 	    }
       
   102 	  }
       
   103 
       
   104 	  const PairInfo* p = pairs;
       
   105 	  for (i = 0; i < nPairs; ++i, p = (const PairInfo*)((char*)p+KERN_PAIRINFO_SIZE)) {
       
   106   	    le_uint32 k = SWAPL(p->key);
       
   107 	    le_uint16 left = (k >> 16) & 0xffff;
       
   108 	    le_uint16 right = k & 0xffff;
       
   109 	    if (left < 256 && right < 256) {
       
   110 	      char c = ids[left];
       
   111 	      if (c > 0x20 && c < 0x7f) {
       
   112 		fprintf(stderr, "%c/", c & 0xff);
       
   113 	      } else {
       
   114 		fprintf(stderr, "%0.2x/", c & 0xff);
       
   115 	      }
       
   116 	      c = ids[right];
       
   117 	      if (c > 0x20 && c < 0x7f) {
       
   118 		fprintf(stderr, "%c ", c & 0xff);
       
   119 	      } else {
       
   120 		fprintf(stderr, "%0.2x ", c & 0xff);
       
   121 	      }
       
   122 	    }
       
   123 	  }
       
   124 	  fflush(stderr);
       
   125 	}
       
   126 #endif
       
   127       }
       
   128     }
       
   129   }
       
   130 }
       
   131   
       
   132 
       
   133 /*
       
   134  * Process the glyph positions.  The positions array has two floats for each
       
   135  * glyph, plus a trailing pair to mark the end of the last glyph.
       
   136  */
       
   137 //void KernTable::process(const LEGlyphID glyphs[], float* positions, le_int32 glyphCount) 
       
   138 void KernTable::process(LEGlyphStorage& storage) 
       
   139 {
       
   140   if (pairs) {
       
   141     LEErrorCode success = LE_NO_ERROR;
       
   142 
       
   143     le_uint32 key = storage[0]; // no need to mask off high bits
       
   144     float adjust = 0;
       
   145     for (int i = 1, e = storage.getGlyphCount(); i < e; ++i) {
       
   146       key = key << 16 | (storage[i] & 0xffff);
       
   147 
       
   148       // argh, to do a binary search, we need to have the pair list in sorted order
       
   149       // but it is not in sorted order on win32 platforms because of the endianness difference
       
   150       // so either I have to swap the element each time I examine it, or I have to swap
       
   151       // all the elements ahead of time and store them in the font
       
   152 
       
   153       const PairInfo* p = pairs;
       
   154       const PairInfo* tp = (const PairInfo*)((char*)p + rangeShift);
       
   155       if (key > SWAPL(tp->key)) {
       
   156 	p = tp;
       
   157       }
       
   158 
       
   159 #if DEBUG
       
   160       fprintf(stderr, "binary search for %0.8x\n", key);
       
   161       fflush(stderr);
       
   162 #endif
       
   163 
       
   164       le_uint32 probe = searchRange;
       
   165       while (probe > KERN_PAIRINFO_SIZE) {
       
   166         probe >>= 1;
       
   167         tp = (const PairInfo*)((char*)p + probe);
       
   168 	le_uint32 tkey = SWAPL(tp->key);
       
   169 #if DEBUG
       
   170 	fprintf(stdout, "   %.3d (%0.8x)\n", ((char*)tp - (char*)pairs)/KERN_PAIRINFO_SIZE, tkey);
       
   171 	fflush(stdout);
       
   172 #endif
       
   173         if (tkey <= key) {
       
   174 	  if (tkey == key) {
       
   175 	    le_int16 value = SWAPW(tp->value);
       
   176 #if DEBUG
       
   177 	    fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n", 
       
   178 		    storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value));
       
   179 	    fflush(stdout);
       
   180 #endif
       
   181 	    adjust += font->xUnitsToPoints(value);
       
   182 	    break;
       
   183 	  }
       
   184 	  p = tp;
       
   185         }
       
   186       }
       
   187 
       
   188       storage.adjustPosition(i, adjust, 0, success);
       
   189     }
       
   190     storage.adjustPosition(storage.getGlyphCount(), adjust, 0, success);
       
   191   }
       
   192 }
       
   193 
       
   194 U_NAMESPACE_END
       
   195