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