Home | History | Annotate | Download | only in layout
      1 /*
      2  *
      3  * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
      4  *
      5  */
      6 
      7 #include "LETypes.h"
      8 #include "OpenTypeTables.h"
      9 #include "GlyphDefinitionTables.h"
     10 #include "GlyphPositionAdjustments.h"
     11 #include "GlyphIterator.h"
     12 #include "LEGlyphStorage.h"
     13 #include "Lookups.h"
     14 #include "LESwaps.h"
     15 
     16 U_NAMESPACE_BEGIN
     17 
     18 GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
     19                              FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
     20   : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
     21     glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
     22     srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
     23     glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
     24 
     25 {
     26     le_int32 glyphCount = glyphStorage.getGlyphCount();
     27 
     28     if (theGlyphDefinitionTableHeader != NULL) {
     29         glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
     30         markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
     31     }
     32 
     33     nextLimit = glyphCount;
     34 
     35     if (rightToLeft) {
     36         direction = -1;
     37         position = glyphCount;
     38         nextLimit = -1;
     39         prevLimit = glyphCount;
     40     }
     41 }
     42 
     43 GlyphIterator::GlyphIterator(GlyphIterator &that)
     44   : glyphStorage(that.glyphStorage)
     45 {
     46     direction    = that.direction;
     47     position     = that.position;
     48     nextLimit    = that.nextLimit;
     49     prevLimit    = that.prevLimit;
     50 
     51     glyphPositionAdjustments = that.glyphPositionAdjustments;
     52     srcIndex = that.srcIndex;
     53     destIndex = that.destIndex;
     54     lookupFlags = that.lookupFlags;
     55     featureMask = that.featureMask;
     56     glyphGroup  = that.glyphGroup;
     57     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     58     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
     59 }
     60 
     61 GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
     62   : glyphStorage(that.glyphStorage)
     63 {
     64     direction    = that.direction;
     65     position     = that.position;
     66     nextLimit    = that.nextLimit;
     67     prevLimit    = that.prevLimit;
     68 
     69     glyphPositionAdjustments = that.glyphPositionAdjustments;
     70     srcIndex = that.srcIndex;
     71     destIndex = that.destIndex;
     72     lookupFlags = that.lookupFlags;
     73     featureMask = newFeatureMask;
     74     glyphGroup  = 0;
     75     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     76     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
     77 }
     78 
     79 GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
     80   : glyphStorage(that.glyphStorage)
     81 {
     82     direction    = that.direction;
     83     position     = that.position;
     84     nextLimit    = that.nextLimit;
     85     prevLimit    = that.prevLimit;
     86 
     87     glyphPositionAdjustments = that.glyphPositionAdjustments;
     88     srcIndex = that.srcIndex;
     89     destIndex = that.destIndex;
     90     lookupFlags = newLookupFlags;
     91     featureMask = that.featureMask;
     92     glyphGroup  = that.glyphGroup;
     93     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     94     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
     95 }
     96 
     97 GlyphIterator::~GlyphIterator()
     98 {
     99     // nothing to do, right?
    100 }
    101 
    102 void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
    103 {
    104     position     = prevLimit;
    105     featureMask  = newFeatureMask;
    106     glyphGroup   = 0;
    107     lookupFlags  = newLookupFlags;
    108 }
    109 
    110 LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)
    111 {
    112     return glyphStorage.insertGlyphs(position, count, success);
    113 }
    114 
    115 le_int32 GlyphIterator::applyInsertions()
    116 {
    117     le_int32 newGlyphCount = glyphStorage.applyInsertions();
    118 
    119     if (direction < 0) {
    120         prevLimit = newGlyphCount;
    121     } else {
    122         nextLimit = newGlyphCount;
    123     }
    124 
    125     return newGlyphCount;
    126 }
    127 
    128 le_int32 GlyphIterator::getCurrStreamPosition() const
    129 {
    130     return position;
    131 }
    132 
    133 le_bool GlyphIterator::isRightToLeft() const
    134 {
    135     return direction < 0;
    136 }
    137 
    138 le_bool GlyphIterator::ignoresMarks() const
    139 {
    140     return (lookupFlags & lfIgnoreMarks) != 0;
    141 }
    142 
    143 le_bool GlyphIterator::baselineIsLogicalEnd() const
    144 {
    145     return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
    146 }
    147 
    148 LEGlyphID GlyphIterator::getCurrGlyphID() const
    149 {
    150     if (direction < 0) {
    151         if (position <= nextLimit || position >= prevLimit) {
    152             return 0xFFFF;
    153         }
    154     } else {
    155         if (position <= prevLimit || position >= nextLimit) {
    156             return 0xFFFF;
    157         }
    158     }
    159 
    160     return glyphStorage[position];
    161 }
    162 
    163 void GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const
    164 {
    165     if (direction < 0) {
    166         if (position <= nextLimit || position >= prevLimit) {
    167             return;
    168         }
    169     } else {
    170         if (position <= prevLimit || position >= nextLimit) {
    171             return;
    172         }
    173     }
    174 
    175     glyphPositionAdjustments->getEntryPoint(position, entryPoint);
    176 }
    177 
    178 void GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const
    179 {
    180     if (direction < 0) {
    181         if (position <= nextLimit || position >= prevLimit) {
    182             return;
    183         }
    184     } else {
    185         if (position <= prevLimit || position >= nextLimit) {
    186             return;
    187         }
    188     }
    189 
    190     glyphPositionAdjustments->getExitPoint(position, exitPoint);
    191 }
    192 
    193 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
    194 {
    195     LEGlyphID glyph = glyphStorage[position];
    196 
    197     glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
    198 }
    199 
    200 void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
    201 {
    202     if (direction < 0) {
    203         if (newPosition >= prevLimit) {
    204             position = prevLimit;
    205             return;
    206         }
    207 
    208         if (newPosition <= nextLimit) {
    209             position = nextLimit;
    210             return;
    211         }
    212     } else {
    213         if (newPosition <= prevLimit) {
    214             position = prevLimit;
    215             return;
    216         }
    217 
    218         if (newPosition >= nextLimit) {
    219             position = nextLimit;
    220             return;
    221         }
    222     }
    223 
    224     position = newPosition - direction;
    225     next();
    226 }
    227 
    228 void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
    229 {
    230     if (direction < 0) {
    231         if (position <= nextLimit || position >= prevLimit) {
    232             return;
    233         }
    234     } else {
    235         if (position <= prevLimit || position >= nextLimit) {
    236             return;
    237         }
    238     }
    239 
    240     glyphPositionAdjustments->setBaseOffset(position, baseOffset);
    241 }
    242 
    243 void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
    244                                                       float xAdvanceAdjust, float yAdvanceAdjust)
    245 {
    246     if (direction < 0) {
    247         if (position <= nextLimit || position >= prevLimit) {
    248             return;
    249         }
    250     } else {
    251         if (position <= prevLimit || position >= nextLimit) {
    252             return;
    253         }
    254     }
    255 
    256     glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);
    257     glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);
    258     glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);
    259     glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);
    260 }
    261 
    262 void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
    263                                                       float xAdvanceAdjust, float yAdvanceAdjust)
    264 {
    265     if (direction < 0) {
    266         if (position <= nextLimit || position >= prevLimit) {
    267             return;
    268         }
    269     } else {
    270         if (position <= prevLimit || position >= nextLimit) {
    271             return;
    272         }
    273     }
    274 
    275     glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);
    276     glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);
    277     glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);
    278     glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
    279 }
    280 
    281 void GlyphIterator::clearCursiveEntryPoint()
    282 {
    283     if (direction < 0) {
    284         if (position <= nextLimit || position >= prevLimit) {
    285             return;
    286         }
    287     } else {
    288         if (position <= prevLimit || position >= nextLimit) {
    289             return;
    290         }
    291     }
    292 
    293     glyphPositionAdjustments->clearEntryPoint(position);
    294 }
    295 
    296 void GlyphIterator::clearCursiveExitPoint()
    297 {
    298     if (direction < 0) {
    299         if (position <= nextLimit || position >= prevLimit) {
    300             return;
    301         }
    302     } else {
    303         if (position <= prevLimit || position >= nextLimit) {
    304             return;
    305         }
    306     }
    307 
    308     glyphPositionAdjustments->clearExitPoint(position);
    309 }
    310 
    311 void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
    312 {
    313     if (direction < 0) {
    314         if (position <= nextLimit || position >= prevLimit) {
    315             return;
    316         }
    317     } else {
    318         if (position <= prevLimit || position >= nextLimit) {
    319             return;
    320         }
    321     }
    322 
    323     glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());
    324 }
    325 
    326 void GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)
    327 {
    328     if (direction < 0) {
    329         if (position <= nextLimit || position >= prevLimit) {
    330             return;
    331         }
    332     } else {
    333         if (position <= prevLimit || position >= nextLimit) {
    334             return;
    335         }
    336     }
    337 
    338     glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());
    339 }
    340 
    341 void GlyphIterator::setCursiveGlyph()
    342 {
    343     if (direction < 0) {
    344         if (position <= nextLimit || position >= prevLimit) {
    345             return;
    346         }
    347     } else {
    348         if (position <= prevLimit || position >= nextLimit) {
    349             return;
    350         }
    351     }
    352 
    353     glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());
    354 }
    355 
    356 le_bool GlyphIterator::filterGlyph(le_uint32 index) const
    357 {
    358     LEGlyphID glyphID = glyphStorage[index];
    359     le_int32 glyphClass = gcdNoGlyphClass;
    360 
    361     if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
    362         return TRUE;
    363     }
    364 
    365     if (glyphClassDefinitionTable != NULL) {
    366         glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
    367     }
    368 
    369     switch (glyphClass)
    370     {
    371     case gcdNoGlyphClass:
    372         return FALSE;
    373 
    374     case gcdSimpleGlyph:
    375         return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
    376 
    377     case gcdLigatureGlyph:
    378         return (lookupFlags & lfIgnoreLigatures) != 0;
    379 
    380     case gcdMarkGlyph:
    381     {
    382         if ((lookupFlags & lfIgnoreMarks) != 0) {
    383             return TRUE;
    384         }
    385 
    386         le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
    387 
    388         if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
    389             return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
    390         }
    391 
    392         return FALSE;
    393     }
    394 
    395     case gcdComponentGlyph:
    396         return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
    397 
    398     default:
    399         return FALSE;
    400     }
    401 }
    402 
    403 le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const
    404 {
    405     if (featureMask == 0) {
    406         return TRUE;
    407     }
    408 
    409     LEErrorCode success = LE_NO_ERROR;
    410     FeatureMask fm = glyphStorage.getAuxData(position, success);
    411 
    412     return ((fm & featureMask) == featureMask) && (!matchGroup || (le_int32)(fm & LE_GLYPH_GROUP_MASK) == glyphGroup);
    413 }
    414 
    415 le_bool GlyphIterator::findFeatureTag()
    416 {
    417   //glyphGroup = 0;
    418 
    419     while (nextInternal()) {
    420         if (hasFeatureTag(FALSE)) {
    421             LEErrorCode success = LE_NO_ERROR;
    422 
    423             glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK);
    424             return TRUE;
    425         }
    426     }
    427 
    428     return FALSE;
    429 }
    430 
    431 
    432 le_bool GlyphIterator::nextInternal(le_uint32 delta)
    433 {
    434     le_int32 newPosition = position;
    435 
    436     while (newPosition != nextLimit && delta > 0) {
    437         do {
    438             newPosition += direction;
    439         } while (newPosition != nextLimit && filterGlyph(newPosition));
    440 
    441         delta -= 1;
    442     }
    443 
    444     position = newPosition;
    445 
    446     return position != nextLimit;
    447 }
    448 
    449 le_bool GlyphIterator::next(le_uint32 delta)
    450 {
    451     return nextInternal(delta) && hasFeatureTag(TRUE);
    452 }
    453 
    454 le_bool GlyphIterator::prevInternal(le_uint32 delta)
    455 {
    456     le_int32 newPosition = position;
    457 
    458     while (newPosition != prevLimit && delta > 0) {
    459         do {
    460             newPosition -= direction;
    461         } while (newPosition != prevLimit && filterGlyph(newPosition));
    462 
    463         delta -= 1;
    464     }
    465 
    466     position = newPosition;
    467 
    468     return position != prevLimit;
    469 }
    470 
    471 le_bool GlyphIterator::prev(le_uint32 delta)
    472 {
    473     return prevInternal(delta) && hasFeatureTag(TRUE);
    474 }
    475 
    476 le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
    477 {
    478     le_int32 component = 0;
    479     le_int32 posn;
    480 
    481     for (posn = position; posn != markPosition; posn += direction) {
    482         if (glyphStorage[posn] == 0xFFFE) {
    483             component += 1;
    484         }
    485     }
    486 
    487     return component;
    488 }
    489 
    490 // This is basically prevInternal except that it
    491 // doesn't take a delta argument, and it doesn't
    492 // filter out 0xFFFE glyphs.
    493 le_bool GlyphIterator::findMark2Glyph()
    494 {
    495     le_int32 newPosition = position;
    496 
    497     do {
    498         newPosition -= direction;
    499     } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition));
    500 
    501     position = newPosition;
    502 
    503     return position != prevLimit;
    504 }
    505 
    506 U_NAMESPACE_END
    507