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