2 * @(#)KernTable.cpp 1.1 04/10/13
4 * (C) Copyright IBM Corp. 2004-2005 - All Rights Reserved
9 #include "LEFontInstance.h"
10 #include "LEGlyphStorage.h"
21 le_uint32 key
; // sigh, MSVC compiler gags on union here
22 le_int16 value
; // fword, kern value in funits
24 #define KERN_PAIRINFO_SIZE 6
28 le_uint16 searchRange
;
29 le_uint16 entrySelector
;
32 #define KERN_SUBTABLE_0_HEADER_SIZE 8
34 // Kern table version 0 only
35 struct SubtableHeader
{
40 #define KERN_SUBTABLE_HEADER_SIZE 6
42 // Version 0 only, version 1 has different layout
43 struct KernTableHeader
{
47 #define KERN_TABLE_HEADER_SIZE 4
49 #define COVERAGE_HORIZONTAL 0x1
50 #define COVERAGE_MINIMUM 0x2
51 #define COVERAGE_CROSS 0x4
52 #define COVERAGE_OVERRIDE 0x8
55 * This implementation has support for only one subtable, so if the font has
56 * multiple subtables, only the first will be used. If this turns out to
57 * be a problem in practice we should add it.
59 * This also supports only version 0 of the kern table header, only
60 * Apple supports the latter.
62 * This implementation isn't careful about the kern table flags, and
63 * might invoke kerning when it is not supposed to. That too I'm
64 * leaving for a bug fix.
66 * TODO: support multiple subtables
67 * TODO: respect header flags
69 KernTable::KernTable(const LEFontInstance
* font
, const void* tableData
)
70 : pairs(0), font(font
)
72 const KernTableHeader
* header
= (const KernTableHeader
*)tableData
;
75 fprintf(stderr
, "no kern data\n");
81 // dump first 32 bytes of header
82 for (int i
= 0; i
< 64; ++i
) {
83 fprintf(stderr
, "%0.2x ", ((const char*)tableData
)[i
]&0xff);
84 if (((i
+1)&0xf) == 0) {
85 fprintf(stderr
, "\n");
86 } else if (((i
+1)&0x7) == 0) {
92 if (header
->version
== 0 && SWAPW(header
->nTables
) > 0) {
93 const SubtableHeader
* subhead
= (const SubtableHeader
*)((char*)tableData
+ KERN_TABLE_HEADER_SIZE
);
94 if (subhead
->version
== 0) {
95 coverage
= SWAPW(subhead
->coverage
);
96 if (coverage
& COVERAGE_HORIZONTAL
) { // only handle horizontal kerning
97 const Subtable_0
* table
= (const Subtable_0
*)((char*)subhead
+ KERN_SUBTABLE_HEADER_SIZE
);
98 nPairs
= SWAPW(table
->nPairs
);
99 searchRange
= SWAPW(table
->searchRange
);
100 entrySelector
= SWAPW(table
->entrySelector
);
101 rangeShift
= SWAPW(table
->rangeShift
);
102 pairs
= (const PairInfo
*)((char*)table
+ KERN_SUBTABLE_0_HEADER_SIZE
);
105 fprintf(stderr
, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage
, nPairs
, pairs
);
106 fprintf(stderr
, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange
, entrySelector
, rangeShift
);
109 // dump part of the pair list
111 for (int i
= 256; --i
>= 0;) {
112 LEGlyphID id
= font
->mapCharToGlyph(i
);
118 const PairInfo
* p
= pairs
;
119 for (i
= 0; i
< nPairs
; ++i
, p
= (const PairInfo
*)((char*)p
+KERN_PAIRINFO_SIZE
)) {
120 le_uint32 k
= SWAPL(p
->key
);
121 le_uint16 left
= (k
>> 16) & 0xffff;
122 le_uint16 right
= k
& 0xffff;
123 if (left
< 256 && right
< 256) {
125 if (c
> 0x20 && c
< 0x7f) {
126 fprintf(stderr
, "%c/", c
& 0xff);
128 fprintf(stderr
, "%0.2x/", c
& 0xff);
131 if (c
> 0x20 && c
< 0x7f) {
132 fprintf(stderr
, "%c ", c
& 0xff);
134 fprintf(stderr
, "%0.2x ", c
& 0xff);
147 * Process the glyph positions. The positions array has two floats for each
148 * glyph, plus a trailing pair to mark the end of the last glyph.
150 void KernTable::process(LEGlyphStorage
& storage
)
153 LEErrorCode success
= LE_NO_ERROR
;
155 le_uint32 key
= storage
[0]; // no need to mask off high bits
157 for (int i
= 1, e
= storage
.getGlyphCount(); i
< e
; ++i
) {
158 key
= key
<< 16 | (storage
[i
] & 0xffff);
160 // argh, to do a binary search, we need to have the pair list in sorted order
161 // but it is not in sorted order on win32 platforms because of the endianness difference
162 // so either I have to swap the element each time I examine it, or I have to swap
163 // all the elements ahead of time and store them in the font
165 const PairInfo
* p
= pairs
;
166 const PairInfo
* tp
= (const PairInfo
*)((char*)p
+ rangeShift
);
167 if (key
> SWAPL(tp
->key
)) {
172 fprintf(stderr
, "binary search for %0.8x\n", key
);
175 le_uint32 probe
= searchRange
;
176 while (probe
> KERN_PAIRINFO_SIZE
) {
178 tp
= (const PairInfo
*)((char*)p
+ probe
);
179 le_uint32 tkey
= SWAPL(tp
->key
);
181 fprintf(stdout
, " %.3d (%0.8x)\n", ((char*)tp
- (char*)pairs
)/KERN_PAIRINFO_SIZE
, tkey
);
185 le_int16 value
= SWAPW(tp
->value
);
187 fprintf(stdout
, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n",
188 storage
[i
-1], storage
[i
], i
, value
& 0xffff, font
->xUnitsToPoints(value
));
191 adjust
+= font
->xUnitsToPoints(value
);
198 storage
.adjustPosition(i
, adjust
, 0, success
);
200 storage
.adjustPosition(storage
.getGlyphCount(), adjust
, 0, success
);