]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
57a6839d | 3 | * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved |
b75a7d8f A |
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" | |
374ca955 | 14 | #include "LEGlyphStorage.h" |
b75a7d8f A |
15 | #include "LESwaps.h" |
16 | ||
17 | U_NAMESPACE_BEGIN | |
18 | ||
19 | #define ExtendedComplement(m) ((le_int32) (~((le_uint32) (m)))) | |
374ca955 | 20 | #define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m)) |
b75a7d8f A |
21 | #define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v)) |
22 | ||
374ca955 | 23 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor) |
b75a7d8f | 24 | |
57a6839d A |
25 | LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success) |
26 | : StateTableProcessor(morphSubtableHeader, success), ligatureSubstitutionHeader(morphSubtableHeader, success) | |
b75a7d8f | 27 | { |
57a6839d | 28 | if(LE_FAILURE(success)) return; |
b75a7d8f A |
29 | ligatureActionTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureActionTableOffset); |
30 | componentTableOffset = SWAPW(ligatureSubstitutionHeader->componentTableOffset); | |
31 | ligatureTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureTableOffset); | |
32 | ||
57a6839d | 33 | entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY); |
b75a7d8f A |
34 | } |
35 | ||
36 | LigatureSubstitutionProcessor::~LigatureSubstitutionProcessor() | |
37 | { | |
38 | } | |
39 | ||
40 | void LigatureSubstitutionProcessor::beginStateTable() | |
41 | { | |
42 | m = -1; | |
43 | } | |
44 | ||
374ca955 | 45 | ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) |
b75a7d8f | 46 | { |
57a6839d A |
47 | LEErrorCode success = LE_NO_ERROR; |
48 | const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success); | |
49 | ||
b75a7d8f A |
50 | ByteOffset newState = SWAPW(entry->newStateOffset); |
51 | le_int16 flags = SWAPW(entry->flags); | |
52 | ||
53 | if (flags & lsfSetComponent) { | |
54 | if (++m >= nComponents) { | |
55 | m = 0; | |
56 | } | |
57 | ||
58 | componentStack[m] = currGlyph; | |
57a6839d A |
59 | } else if ( m == -1) { |
60 | // bad font- skip this glyph. | |
61 | currGlyph++; | |
62 | return newState; | |
b75a7d8f A |
63 | } |
64 | ||
65 | ByteOffset actionOffset = flags & lsfActionOffsetMask; | |
66 | ||
67 | if (actionOffset != 0) { | |
57a6839d | 68 | LEReferenceTo<LigatureActionEntry> ap(stHeader, success, actionOffset); |
b75a7d8f A |
69 | LigatureActionEntry action; |
70 | le_int32 offset, i = 0; | |
71 | le_int32 stack[nComponents]; | |
72 | le_int16 mm = -1; | |
73 | ||
74 | do { | |
75 | le_uint32 componentGlyph = componentStack[m--]; | |
76 | ||
57a6839d A |
77 | action = SWAPL(*ap.getAlias()); |
78 | ap.addObject(success); // ap++ | |
b75a7d8f A |
79 | |
80 | if (m < 0) { | |
81 | m = nComponents - 1; | |
82 | } | |
83 | ||
84 | offset = action & lafComponentOffsetMask; | |
85 | if (offset != 0) { | |
57a6839d A |
86 | LEReferenceToArrayOf<le_int16> offsetTable(stHeader, success, 2 * SignExtend(offset, lafComponentOffsetMask), LE_UNBOUNDED_ARRAY); |
87 | ||
88 | if(LE_FAILURE(success)) { | |
89 | currGlyph++; | |
90 | LE_DEBUG_BAD_FONT("off end of ligature substitution header"); | |
91 | return newState; // get out! bad font | |
92 | } | |
93 | if(componentGlyph > (le_uint32)glyphStorage.getGlyphCount()) { | |
94 | LE_DEBUG_BAD_FONT("preposterous componentGlyph"); | |
95 | currGlyph++; | |
96 | return newState; // get out! bad font | |
97 | } | |
98 | i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success)); | |
b75a7d8f A |
99 | |
100 | if (action & (lafLast | lafStore)) { | |
57a6839d A |
101 | LEReferenceTo<TTGlyphID> ligatureOffset(stHeader, success, i); |
102 | TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias()); | |
103 | ||
104 | glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); | |
105 | if(mm==nComponents) { | |
106 | LE_DEBUG_BAD_FONT("exceeded nComponents"); | |
107 | mm--; // don't overrun the stack. | |
108 | } | |
109 | stack[++mm] = componentGlyph; | |
110 | i = 0; | |
b75a7d8f | 111 | } else { |
57a6839d | 112 | glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF); |
b75a7d8f A |
113 | } |
114 | } | |
57a6839d A |
115 | #if LE_ASSERT_BAD_FONT |
116 | if(m<0) { | |
117 | LE_DEBUG_BAD_FONT("m<0") | |
b75a7d8f | 118 | } |
57a6839d A |
119 | #endif |
120 | } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items | |
b75a7d8f | 121 | |
57a6839d A |
122 | while (mm >= 0) { |
123 | if (++m >= nComponents) { | |
124 | m = 0; | |
125 | } | |
126 | ||
127 | componentStack[m] = stack[mm--]; | |
b75a7d8f A |
128 | } |
129 | } | |
130 | ||
131 | if (!(flags & lsfDontAdvance)) { | |
132 | // should handle reverse too! | |
133 | currGlyph += 1; | |
134 | } | |
135 | ||
136 | return newState; | |
137 | } | |
138 | ||
139 | void LigatureSubstitutionProcessor::endStateTable() | |
140 | { | |
141 | } | |
142 | ||
143 | U_NAMESPACE_END |