Home | History | Annotate | Download | only in layout
      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 
     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 
     32 ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
     33 {
     34 }
     35 
     36 void ContextualGlyphInsertionProcessor2::beginStateTable()
     37 {
     38     markGlyph = 0;
     39 }
     40 
     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 
     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 
    110 void ContextualGlyphInsertionProcessor2::endStateTable()
    111 {
    112 }
    113 
    114 U_NAMESPACE_END
    115