Home | History | Annotate | Download | only in layout
      1 /*
      2  * (C) Copyright IBM Corp. and others 1998 - 2013 - All Rights Reserved
      3  *
      4  */
      5 
      6 #include "LETypes.h"
      7 #include "LayoutTables.h"
      8 #include "MorphTables.h"
      9 #include "SubtableProcessor2.h"
     10 #include "IndicRearrangementProcessor2.h"
     11 #include "ContextualGlyphSubstProc2.h"
     12 #include "LigatureSubstProc2.h"
     13 #include "NonContextualGlyphSubstProc2.h"
     14 #include "ContextualGlyphInsertionProc2.h"
     15 #include "LEGlyphStorage.h"
     16 #include "LESwaps.h"
     17 
     18 U_NAMESPACE_BEGIN
     19 
     20 void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage,
     21                                 le_int32 typoFlags, LEErrorCode &success) const
     22 {
     23   if(LE_FAILURE(success)) return;
     24 
     25   le_uint32 chainCount = SWAPL(this->nChains);
     26   LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]);
     27   /* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference
     28    * to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through.
     29    * We don't want to increment them at the end of the loop, as that would attempt to dereference
     30    * out of range memory.
     31    */
     32   le_uint32 chain;
     33 
     34   for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) {
     35         if (chain>0) {
     36           le_uint32 chainLength = SWAPL(chainHeader->chainLength);
     37           chainHeader.addOffset(chainLength, success); // Don't increment the first time
     38         }
     39         FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
     40         le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
     41         le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
     42         LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader,
     43               success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]);
     44         le_uint32 subtable;
     45         if(LE_FAILURE(success)) break; // malformed table
     46 
     47         if (typoFlags != 0) {
     48            le_uint32 featureEntry;
     49            LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries);
     50            if(LE_FAILURE(success)) break;
     51             // Feature subtables
     52             for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
     53                 const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success);
     54                 le_int16 featureType = SWAPW(featureTableEntry.featureType);
     55                 le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting);
     56                 le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags);
     57                 le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags);
     58                 switch (featureType) {
     59                     case ligaturesType:
     60                         if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){
     61                             flag &= disableFlags;
     62                             flag |= enableFlags;
     63                         } else {
     64                             if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) ||
     65                                 ((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) ||
     66                                 ((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) ||
     67                                 ((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) {
     68                                 flag &= disableFlags;
     69                                 flag |= enableFlags;
     70                             }
     71                         }
     72                         break;
     73                     case letterCaseType:
     74                         if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) {
     75                             flag &= disableFlags;
     76                             flag |= enableFlags;
     77                         }
     78                         break;
     79                     case verticalSubstitutionType:
     80                         break;
     81                     case linguisticRearrangementType:
     82                         break;
     83                     case numberSpacingType:
     84                         break;
     85                     case smartSwashType:
     86                         if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){
     87                             flag &= disableFlags;
     88                             flag |= enableFlags;
     89                         }
     90                         break;
     91                     case diacriticsType:
     92                         break;
     93                     case verticalPositionType:
     94                         break;
     95                     case fractionsType:
     96                         if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) ||
     97                             ((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) {
     98                             flag &= disableFlags;
     99                             flag |= enableFlags;
    100                         } else {
    101                             flag &= disableFlags;
    102                         }
    103                         break;
    104                     case typographicExtrasType:
    105                         if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) {
    106                             flag &= disableFlags;
    107                             flag |= enableFlags;
    108                         }
    109                         break;
    110                     case mathematicalExtrasType:
    111                         break;
    112                     case ornamentSetsType:
    113                         break;
    114                     case characterAlternativesType:
    115                         break;
    116                     case designComplexityType:
    117                         if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) ||
    118                             ((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) ||
    119                             ((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) ||
    120                             ((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) ||
    121                             ((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) ||
    122                             ((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) ||
    123                             ((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) {
    124 
    125                             flag &= disableFlags;
    126                             flag |= enableFlags;
    127                         }
    128                         break;
    129                     case styleOptionsType:
    130                         break;
    131                     case characterShapeType:
    132                         break;
    133                     case numberCaseType:
    134                         break;
    135                     case textSpacingType:
    136                         break;
    137                     case transliterationType:
    138                         break;
    139                     case annotationType:
    140                         if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) {
    141                             flag &= disableFlags;
    142                             flag |= enableFlags;
    143                         }
    144                         break;
    145                     case kanaSpacingType:
    146                         break;
    147                     case ideographicSpacingType:
    148                         break;
    149                     case rubyKanaType:
    150                         if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) {
    151                             flag &= disableFlags;
    152                             flag |= enableFlags;
    153                         }
    154                         break;
    155                     case cjkRomanSpacingType:
    156                         break;
    157                     default:
    158                         break;
    159                 }
    160             }
    161         }
    162 
    163         for (subtable = 0;  LE_SUCCESS(success) && subtable < nSubtables; subtable++) {
    164             if(subtable>0)  {
    165               le_uint32 length = SWAPL(subtableHeader->length);
    166               subtableHeader.addOffset(length, success); // Don't addOffset for the last entry.
    167             }
    168             le_uint32 coverage = SWAPL(subtableHeader->coverage);
    169             FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
    170             // should check coverage more carefully...
    171             if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
    172               subtableHeader->process(subtableHeader, glyphStorage, success);
    173             }
    174         }
    175     }
    176 }
    177 
    178 void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
    179 {
    180     SubtableProcessor2 *processor = NULL;
    181 
    182     switch (SWAPL(coverage) & scfTypeMask2)
    183     {
    184     case mstIndicRearrangement:
    185         processor = new IndicRearrangementProcessor2(base, success);
    186         break;
    187 
    188     case mstContextualGlyphSubstitution:
    189         processor = new ContextualGlyphSubstitutionProcessor2(base, success);
    190         break;
    191 
    192     case mstLigatureSubstitution:
    193         processor = new LigatureSubstitutionProcessor2(base, success);
    194         break;
    195 
    196     case mstReservedUnused:
    197         break;
    198 
    199     case mstNonContextualGlyphSubstitution:
    200         processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success);
    201         break;
    202 
    203 
    204     case mstContextualGlyphInsertion:
    205         processor = new ContextualGlyphInsertionProcessor2(base, success);
    206         break;
    207 
    208     default:
    209         return;
    210         break; /*NOTREACHED*/
    211     }
    212 
    213     if (processor != NULL) {
    214       processor->process(glyphStorage, success);
    215         delete processor;
    216     } else {
    217       if(LE_SUCCESS(success)) {
    218         success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out.
    219       }
    220     }
    221 }
    222 
    223 U_NAMESPACE_END
    224