• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * (C) Copyright IBM Corp.  and others 1998-2013 - All Rights Reserved
4  *
5  */
6 
7 #include "LETypes.h"
8 #include "MorphTables.h"
9 #include "StateTables.h"
10 #include "MorphStateTables.h"
11 #include "SubtableProcessor2.h"
12 #include "StateTableProcessor2.h"
13 #include "ContextualGlyphInsertionProc2.h"
14 #include "LEGlyphStorage.h"
15 #include "LESwaps.h"
16 
17 U_NAMESPACE_BEGIN
18 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)19 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
20 
21 ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(
22          const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
23   : StateTableProcessor2(morphSubtableHeader, success)
24 {
25   contextualGlyphHeader = LEReferenceTo<ContextualGlyphInsertionHeader2>(morphSubtableHeader, success);
26   if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return;
27   le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
28   insertionTable = LEReferenceToArrayOf<le_uint16>(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY);
29   entryTable = LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
30 }
31 
~ContextualGlyphInsertionProcessor2()32 ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
33 {
34 }
35 
beginStateTable()36 void ContextualGlyphInsertionProcessor2::beginStateTable()
37 {
38     markGlyph = 0;
39 }
40 
doInsertion(LEGlyphStorage & glyphStorage,le_int16 atGlyph,le_int16 & index,le_int16 count,le_bool,le_bool isBefore,LEErrorCode & success)41 void ContextualGlyphInsertionProcessor2::doInsertion(LEGlyphStorage &glyphStorage,
42                                                      le_int16 atGlyph,
43                                                      le_int16 &index,
44                                                      le_int16 count,
45                                                      le_bool /* isKashidaLike */,
46                                                      le_bool isBefore,
47                                                      LEErrorCode &success) {
48   LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(atGlyph, count + 1, success);
49 
50   if(LE_FAILURE(success) || insertGlyphs==NULL) {
51     return;
52   }
53 
54   // Note: Kashida vs Split Vowel seems to only affect selection and highlighting.
55   // We note the flag, but do not layout different.
56   // https://developer.apple.com/fonts/TTRefMan/RM06/Chap6mort.html
57 
58   le_int16 targetIndex = 0;
59   if(isBefore) {
60     // insert at beginning
61     insertGlyphs[targetIndex++] = glyphStorage[atGlyph];
62   } else {
63     // insert at end
64     insertGlyphs[count] = glyphStorage[atGlyph];
65   }
66 
67   while(count--) {
68     insertGlyphs[targetIndex++] = insertionTable.getObject(index++, success);
69   }
70   glyphStorage.applyInsertions();
71 }
72 
processStateEntry(LEGlyphStorage & glyphStorage,le_int32 & currGlyph,EntryTableIndex2 index,LEErrorCode & success)73 le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
74                                                                 EntryTableIndex2 index, LEErrorCode &success)
75 {
76     const ContextualGlyphInsertionStateEntry2 *entry = entryTable.getAlias(index, success);
77 
78     if(LE_FAILURE(success)) return 0; // TODO- which state?
79 
80     le_uint16 newState = SWAPW(entry->newStateIndex);
81     le_uint16 flags = SWAPW(entry->flags);
82 
83     le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
84     if (markIndex > 0) {
85         le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
86         le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike);
87         le_bool isBefore = (flags & cgiMarkInsertBefore);
88         doInsertion(glyphStorage, markGlyph, markIndex, count, isKashidaLike, isBefore, success);
89     }
90 
91     le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
92     if (currIndex > 0) {
93         le_int16 count = flags & cgiCurrentInsertCountMask;
94         le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike);
95         le_bool isBefore = (flags & cgiCurrentInsertBefore);
96         doInsertion(glyphStorage, currGlyph, currIndex, count, isKashidaLike, isBefore, success);
97     }
98 
99     if (flags & cgiSetMark) {
100         markGlyph = currGlyph;
101     }
102 
103     if (!(flags & cgiDontAdvance)) {
104         currGlyph += dir;
105     }
106 
107     return newState;
108 }
109 
endStateTable()110 void ContextualGlyphInsertionProcessor2::endStateTable()
111 {
112 }
113 
114 U_NAMESPACE_END
115