jdk/src/share/native/sun/font/layout/ContextualGlyphInsertionProc2.cpp
changeset 16891 91e99bed64ae
parent 16889 3df90f344221
equal deleted inserted replaced
16890:36b30720a997 16891:91e99bed64ae
    41 
    41 
    42 U_NAMESPACE_BEGIN
    42 U_NAMESPACE_BEGIN
    43 
    43 
    44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
    44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
    45 
    45 
    46 ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
    46 ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(
    47   : StateTableProcessor2(morphSubtableHeader)
    47          const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
       
    48   : StateTableProcessor2(morphSubtableHeader, success)
    48 {
    49 {
    49     contextualGlyphHeader = (const ContextualGlyphInsertionHeader2 *) morphSubtableHeader;
    50   contextualGlyphHeader = LEReferenceTo<ContextualGlyphInsertionHeader2>(morphSubtableHeader, success);
    50     le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
    51   if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return;
    51     insertionTable = ((le_uint16 *) ((char *)&stateTableHeader->stHeader + insertionTableOffset));
    52   le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
    52     entryTable = (const ContextualGlyphInsertionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
    53   insertionTable = LEReferenceToArrayOf<le_uint16>(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY);
       
    54   entryTable = LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
    53 }
    55 }
    54 
    56 
    55 ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
    57 ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
    56 {
    58 {
    57 }
    59 }
    59 void ContextualGlyphInsertionProcessor2::beginStateTable()
    61 void ContextualGlyphInsertionProcessor2::beginStateTable()
    60 {
    62 {
    61     markGlyph = 0;
    63     markGlyph = 0;
    62 }
    64 }
    63 
    65 
    64 le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
    66 void ContextualGlyphInsertionProcessor2::doInsertion(LEGlyphStorage &glyphStorage,
       
    67                                                      le_int16 atGlyph,
       
    68                                                      le_int16 &index,
       
    69                                                      le_int16 count,
       
    70                                                      le_bool /* isKashidaLike */,
       
    71                                                      le_bool isBefore,
       
    72                                                      LEErrorCode &success) {
       
    73   LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(atGlyph, count + 1, success);
       
    74 
       
    75   if(LE_FAILURE(success) || insertGlyphs==NULL) {
       
    76     return;
       
    77   }
       
    78 
       
    79   // Note: Kashida vs Split Vowel seems to only affect selection and highlighting.
       
    80   // We note the flag, but do not layout different.
       
    81   // https://developer.apple.com/fonts/TTRefMan/RM06/Chap6mort.html
       
    82 
       
    83   le_int16 targetIndex = 0;
       
    84   if(isBefore) {
       
    85     // insert at beginning
       
    86     insertGlyphs[targetIndex++] = glyphStorage[atGlyph];
       
    87   } else {
       
    88     // insert at end
       
    89     insertGlyphs[count] = glyphStorage[atGlyph];
       
    90   }
       
    91 
       
    92   while(count--) {
       
    93     insertGlyphs[targetIndex++] = insertionTable.getObject(index++, success);
       
    94   }
       
    95   glyphStorage.applyInsertions();
       
    96 }
       
    97 
       
    98 le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
       
    99                                                                 EntryTableIndex2 index, LEErrorCode &success)
    65 {
   100 {
    66     const ContextualGlyphInsertionStateEntry2 *entry = &entryTable[index];
   101     const ContextualGlyphInsertionStateEntry2 *entry = entryTable.getAlias(index, success);
       
   102 
       
   103     if(LE_FAILURE(success)) return 0; // TODO- which state?
       
   104 
    67     le_uint16 newState = SWAPW(entry->newStateIndex);
   105     le_uint16 newState = SWAPW(entry->newStateIndex);
    68     le_uint16 flags = SWAPW(entry->flags);
   106     le_uint16 flags = SWAPW(entry->flags);
    69     le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
   107 
    70     le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
   108     le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
    71     int i = 0;
       
    72 
       
    73     if (markIndex > 0) {
   109     if (markIndex > 0) {
    74         le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
   110         le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
    75         if (!(flags & cgiMarkedIsKashidaLike)) {
   111         le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike);
    76             // extra glyph(s) will be added directly before/after the specified marked glyph
   112         le_bool isBefore = (flags & cgiMarkInsertBefore);
    77             if (!(flags & cgiMarkInsertBefore)) {
   113         doInsertion(glyphStorage, markGlyph, markIndex, count, isKashidaLike, isBefore, success);
    78                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
       
    79                 for (i = 0; i < count; i++, markIndex++) {
       
    80                     insertGlyphs[i] = insertionTable[markIndex];
       
    81                 }
       
    82                 insertGlyphs[i] = glyphStorage[markGlyph];
       
    83                 glyphStorage.applyInsertions();
       
    84             } else {
       
    85                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
       
    86                 insertGlyphs[0] = glyphStorage[markGlyph];
       
    87                 for (i = 1; i < count + 1; i++, markIndex++) {
       
    88                     insertGlyphs[i] = insertionTable[markIndex];
       
    89                 }
       
    90                 glyphStorage.applyInsertions();
       
    91             }
       
    92         } else {
       
    93             // inserted as a split-vowel-like insertion
       
    94             // extra glyph(s) will be inserted some distance away from the marked glyph
       
    95             if (!(flags & cgiMarkInsertBefore)) {
       
    96                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
       
    97                 for (i = 0; i < count; i++, markIndex++) {
       
    98                     insertGlyphs[i] = insertionTable[markIndex];
       
    99                 }
       
   100                 insertGlyphs[i] = glyphStorage[markGlyph];
       
   101                 glyphStorage.applyInsertions();
       
   102             } else {
       
   103                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
       
   104                 insertGlyphs[0] = glyphStorage[markGlyph];
       
   105                 for (i = 1; i < count + 1; i++, markIndex++) {
       
   106                     insertGlyphs[i] = insertionTable[markIndex];
       
   107                 }
       
   108                 glyphStorage.applyInsertions();
       
   109             }
       
   110         }
       
   111     }
   114     }
   112 
   115 
       
   116     le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
   113     if (currIndex > 0) {
   117     if (currIndex > 0) {
   114         le_int16 count = flags & cgiCurrentInsertCountMask;
   118         le_int16 count = flags & cgiCurrentInsertCountMask;
   115         if (!(flags & cgiCurrentIsKashidaLike)) {
   119         le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike);
   116             // extra glyph(s) will be added directly before/after the specified current glyph
   120         le_bool isBefore = (flags & cgiCurrentInsertBefore);
   117             if (!(flags & cgiCurrentInsertBefore)) {
   121         doInsertion(glyphStorage, currGlyph, currIndex, count, isKashidaLike, isBefore, success);
   118                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
       
   119                 for (i = 0; i < count; i++, currIndex++) {
       
   120                     insertGlyphs[i] = insertionTable[currIndex];
       
   121                 }
       
   122                 insertGlyphs[i] = glyphStorage[currGlyph];
       
   123                 glyphStorage.applyInsertions();
       
   124             } else {
       
   125                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
       
   126                 insertGlyphs[0] = glyphStorage[currGlyph];
       
   127                 for (i = 1; i < count + 1; i++, currIndex++) {
       
   128                     insertGlyphs[i] = insertionTable[currIndex];
       
   129                 }
       
   130                 glyphStorage.applyInsertions();
       
   131             }
       
   132         } else {
       
   133             // inserted as a split-vowel-like insertion
       
   134             // extra glyph(s) will be inserted some distance away from the current glyph
       
   135             if (!(flags & cgiCurrentInsertBefore)) {
       
   136                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
       
   137                 for (i = 0; i < count; i++, currIndex++) {
       
   138                     insertGlyphs[i] = insertionTable[currIndex];
       
   139                 }
       
   140                 insertGlyphs[i] = glyphStorage[currGlyph];
       
   141                 glyphStorage.applyInsertions();
       
   142             } else {
       
   143                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
       
   144                 insertGlyphs[0] = glyphStorage[currGlyph];
       
   145                 for (i = 1; i < count + 1; i++, currIndex++) {
       
   146                     insertGlyphs[i] = insertionTable[currIndex];
       
   147                 }
       
   148                 glyphStorage.applyInsertions();
       
   149             }
       
   150         }
       
   151     }
   122     }
   152 
   123 
   153     if (flags & cgiSetMark) {
   124     if (flags & cgiSetMark) {
   154         markGlyph = currGlyph;
   125         markGlyph = currGlyph;
   155     }
   126     }