jdk/src/share/native/sun/font/layout/ContextualGlyphInsertionProc2.cpp
changeset 16891 91e99bed64ae
parent 16889 3df90f344221
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphInsertionProc2.cpp	Tue Feb 26 10:07:26 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphInsertionProc2.cpp	Thu Mar 07 10:02:20 2013 -0800
@@ -43,13 +43,15 @@
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
 
-ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
-  : StateTableProcessor2(morphSubtableHeader)
+ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(
+         const LEReferenceTo<MorphSubtableHeader2> &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<ContextualGlyphInsertionHeader2>(morphSubtableHeader, success);
+  if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return;
+  le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
+  insertionTable = LEReferenceToArrayOf<le_uint16>(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY);
+  entryTable = LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
 }
 
 ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
@@ -61,93 +63,62 @@
     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;
-
     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) {