|
1 /* |
|
2 * |
|
3 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved |
|
4 * |
|
5 */ |
|
6 |
|
7 #include "LETypes.h" |
|
8 #include "MorphTables.h" |
|
9 #include "StateTables.h" |
|
10 #include "MorphStateTables.h" |
|
11 #include "SubtableProcessor.h" |
|
12 #include "StateTableProcessor.h" |
|
13 #include "LigatureSubstProc.h" |
|
14 #include "LEGlyphStorage.h" |
|
15 #include "LESwaps.h" |
|
16 |
|
17 U_NAMESPACE_BEGIN |
|
18 |
|
19 #define ExtendedComplement(m) ((le_int32) (~((le_uint32) (m)))) |
|
20 #define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m)) |
|
21 #define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v)) |
|
22 |
|
23 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor) |
|
24 |
|
25 LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader) |
|
26 : StateTableProcessor(morphSubtableHeader) |
|
27 { |
|
28 ligatureSubstitutionHeader = (const LigatureSubstitutionHeader *) morphSubtableHeader; |
|
29 ligatureActionTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureActionTableOffset); |
|
30 componentTableOffset = SWAPW(ligatureSubstitutionHeader->componentTableOffset); |
|
31 ligatureTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureTableOffset); |
|
32 |
|
33 entryTable = (const LigatureSubstitutionStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset); |
|
34 } |
|
35 |
|
36 LigatureSubstitutionProcessor::~LigatureSubstitutionProcessor() |
|
37 { |
|
38 } |
|
39 |
|
40 void LigatureSubstitutionProcessor::beginStateTable() |
|
41 { |
|
42 m = -1; |
|
43 } |
|
44 |
|
45 ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) |
|
46 { |
|
47 const LigatureSubstitutionStateEntry *entry = &entryTable[index]; |
|
48 ByteOffset newState = SWAPW(entry->newStateOffset); |
|
49 le_int16 flags = SWAPW(entry->flags); |
|
50 |
|
51 if (flags & lsfSetComponent) { |
|
52 if (++m >= nComponents) { |
|
53 m = 0; |
|
54 } |
|
55 |
|
56 componentStack[m] = currGlyph; |
|
57 } |
|
58 |
|
59 ByteOffset actionOffset = flags & lsfActionOffsetMask; |
|
60 |
|
61 if (actionOffset != 0) { |
|
62 const LigatureActionEntry *ap = (const LigatureActionEntry *) ((char *) &ligatureSubstitutionHeader->stHeader + actionOffset); |
|
63 LigatureActionEntry action; |
|
64 le_int32 offset, i = 0; |
|
65 le_int32 stack[nComponents]; |
|
66 le_int16 mm = -1; |
|
67 |
|
68 do { |
|
69 le_uint32 componentGlyph = componentStack[m--]; |
|
70 |
|
71 action = SWAPL(*ap++); |
|
72 |
|
73 if (m < 0) { |
|
74 m = nComponents - 1; |
|
75 } |
|
76 |
|
77 offset = action & lafComponentOffsetMask; |
|
78 if (offset != 0) { |
|
79 const le_int16 *offsetTable = (const le_int16 *)((char *) &ligatureSubstitutionHeader->stHeader + 2 * SignExtend(offset, lafComponentOffsetMask)); |
|
80 |
|
81 i += SWAPW(offsetTable[LE_GET_GLYPH(glyphStorage[componentGlyph])]); |
|
82 |
|
83 if (action & (lafLast | lafStore)) { |
|
84 const TTGlyphID *ligatureOffset = (const TTGlyphID *) ((char *) &ligatureSubstitutionHeader->stHeader + i); |
|
85 TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset); |
|
86 |
|
87 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); |
|
88 stack[++mm] = componentGlyph; |
|
89 i = 0; |
|
90 } else { |
|
91 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF); |
|
92 } |
|
93 } |
|
94 } while (!(action & lafLast)); |
|
95 |
|
96 while (mm >= 0) { |
|
97 if (++m >= nComponents) { |
|
98 m = 0; |
|
99 } |
|
100 |
|
101 componentStack[m] = stack[mm--]; |
|
102 } |
|
103 } |
|
104 |
|
105 if (!(flags & lsfDontAdvance)) { |
|
106 // should handle reverse too! |
|
107 currGlyph += 1; |
|
108 } |
|
109 |
|
110 return newState; |
|
111 } |
|
112 |
|
113 void LigatureSubstitutionProcessor::endStateTable() |
|
114 { |
|
115 } |
|
116 |
|
117 U_NAMESPACE_END |