X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/51004dcb01e06fef634b61be77ed73dd61cb6db9..249c4c5ea9376c24572daf9c2effa7484a282f14:/icuSources/layout/ContextualGlyphInsertionProc2.cpp diff --git a/icuSources/layout/ContextualGlyphInsertionProc2.cpp b/icuSources/layout/ContextualGlyphInsertionProc2.cpp index ee912ae4..08048b73 100644 --- a/icuSources/layout/ContextualGlyphInsertionProc2.cpp +++ b/icuSources/layout/ContextualGlyphInsertionProc2.cpp @@ -18,13 +18,15 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2) -ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader) - : StateTableProcessor2(morphSubtableHeader) +ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2( + const LEReferenceTo &morphSubtableHeader, LEErrorCode &success) + : StateTableProcessor2(morphSubtableHeader, success) { - contextualGlyphHeader = (const ContextualGlyphInsertionHeader2 *) morphSubtableHeader; - le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset); - insertionTable = ((le_uint16 *) ((char *)&stateTableHeader->stHeader + insertionTableOffset)); - entryTable = (const ContextualGlyphInsertionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset); + contextualGlyphHeader = LEReferenceTo(morphSubtableHeader, success); + if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return; + le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset); + insertionTable = LEReferenceToArrayOf(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY); + entryTable = LEReferenceToArrayOf(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY); } ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2() @@ -36,95 +38,64 @@ void ContextualGlyphInsertionProcessor2::beginStateTable() markGlyph = 0; } -le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index) +void ContextualGlyphInsertionProcessor2::doInsertion(LEGlyphStorage &glyphStorage, + le_int16 atGlyph, + le_int16 &index, + le_int16 count, + le_bool /* isKashidaLike */, + le_bool isBefore, + LEErrorCode &success) { + LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(atGlyph, count + 1, success); + + if(LE_FAILURE(success) || insertGlyphs==NULL) { + return; + } + + // Note: Kashida vs Split Vowel seems to only affect selection and highlighting. + // We note the flag, but do not layout different. + // https://developer.apple.com/fonts/TTRefMan/RM06/Chap6mort.html + + le_int16 targetIndex = 0; + if(isBefore) { + // insert at beginning + insertGlyphs[targetIndex++] = glyphStorage[atGlyph]; + } else { + // insert at end + insertGlyphs[count] = glyphStorage[atGlyph]; + } + + while(count--) { + insertGlyphs[targetIndex++] = insertionTable.getObject(index++, success); + } + glyphStorage.applyInsertions(); +} + +le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, + EntryTableIndex2 index, LEErrorCode &success) { - const ContextualGlyphInsertionStateEntry2 *entry = &entryTable[index]; + const ContextualGlyphInsertionStateEntry2 *entry = entryTable.getAlias(index, success); + + if(LE_FAILURE(success)) return 0; // TODO- which state? + le_uint16 newState = SWAPW(entry->newStateIndex); le_uint16 flags = SWAPW(entry->flags); - le_int16 currIndex = SWAPW(entry->currentInsertionListIndex); - le_int16 markIndex = SWAPW(entry->markedInsertionListIndex); - int i = 0; + le_int16 markIndex = SWAPW(entry->markedInsertionListIndex); if (markIndex > 0) { le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5; - if (!(flags & cgiMarkedIsKashidaLike)) { - // extra glyph(s) will be added directly before/after the specified marked glyph - if (!(flags & cgiMarkInsertBefore)) { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1); - for (i = 0; i < count; i++, markIndex++) { - insertGlyphs[i] = insertionTable[markIndex]; - } - insertGlyphs[i] = glyphStorage[markGlyph]; - glyphStorage.applyInsertions(); - } else { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1); - insertGlyphs[0] = glyphStorage[markGlyph]; - for (i = 1; i < count + 1; i++, markIndex++) { - insertGlyphs[i] = insertionTable[markIndex]; - } - glyphStorage.applyInsertions(); - } - } else { - // inserted as a split-vowel-like insertion - // extra glyph(s) will be inserted some distance away from the marked glyph - if (!(flags & cgiMarkInsertBefore)) { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1); - for (i = 0; i < count; i++, markIndex++) { - insertGlyphs[i] = insertionTable[markIndex]; - } - insertGlyphs[i] = glyphStorage[markGlyph]; - glyphStorage.applyInsertions(); - } else { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1); - insertGlyphs[0] = glyphStorage[markGlyph]; - for (i = 1; i < count + 1; i++, markIndex++) { - insertGlyphs[i] = insertionTable[markIndex]; - } - glyphStorage.applyInsertions(); - } - } + le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike); + le_bool isBefore = (flags & cgiMarkInsertBefore); + doInsertion(glyphStorage, markGlyph, markIndex, count, isKashidaLike, isBefore, success); } + le_int16 currIndex = SWAPW(entry->currentInsertionListIndex); if (currIndex > 0) { le_int16 count = flags & cgiCurrentInsertCountMask; - if (!(flags & cgiCurrentIsKashidaLike)) { - // extra glyph(s) will be added directly before/after the specified current glyph - if (!(flags & cgiCurrentInsertBefore)) { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1); - for (i = 0; i < count; i++, currIndex++) { - insertGlyphs[i] = insertionTable[currIndex]; - } - insertGlyphs[i] = glyphStorage[currGlyph]; - glyphStorage.applyInsertions(); - } else { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1); - insertGlyphs[0] = glyphStorage[currGlyph]; - for (i = 1; i < count + 1; i++, currIndex++) { - insertGlyphs[i] = insertionTable[currIndex]; - } - glyphStorage.applyInsertions(); - } - } else { - // inserted as a split-vowel-like insertion - // extra glyph(s) will be inserted some distance away from the current glyph - if (!(flags & cgiCurrentInsertBefore)) { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1); - for (i = 0; i < count; i++, currIndex++) { - insertGlyphs[i] = insertionTable[currIndex]; - } - insertGlyphs[i] = glyphStorage[currGlyph]; - glyphStorage.applyInsertions(); - } else { - LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1); - insertGlyphs[0] = glyphStorage[currGlyph]; - for (i = 1; i < count + 1; i++, currIndex++) { - insertGlyphs[i] = insertionTable[currIndex]; - } - glyphStorage.applyInsertions(); - } - } + le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike); + le_bool isBefore = (flags & cgiCurrentInsertBefore); + doInsertion(glyphStorage, currGlyph, currIndex, count, isKashidaLike, isBefore, success); } - + if (flags & cgiSetMark) { markGlyph = currGlyph; }