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
17U_NAMESPACE_BEGIN
18
19UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
20
21ContextualGlyphInsertionProcessor2::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
32ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
33{
34}
35
36void ContextualGlyphInsertionProcessor2::beginStateTable()
37{
38    markGlyph = 0;
39}
40
41void 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
73le_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
110void ContextualGlyphInsertionProcessor2::endStateTable()
111{
112}
113
114U_NAMESPACE_END
115