os/textandloc/fontservices/textshaperplugin/IcuSource/layout/LookupProcessor.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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 "OpenTypeUtilities.h"
sl@0
     9
#include "LEFontInstance.h"
sl@0
    10
#include "OpenTypeTables.h"
sl@0
    11
#include "Features.h"
sl@0
    12
#include "Lookups.h"
sl@0
    13
#include "ScriptAndLanguage.h"
sl@0
    14
#include "GlyphDefinitionTables.h"
sl@0
    15
#include "GlyphIterator.h"
sl@0
    16
#include "LookupProcessor.h"
sl@0
    17
#include "LEGlyphStorage.h"
sl@0
    18
#include "LESwaps.h"
sl@0
    19
sl@0
    20
U_NAMESPACE_BEGIN
sl@0
    21
sl@0
    22
const LETag LookupProcessor::notSelected    = 0x00000000;
sl@0
    23
const LETag LookupProcessor::defaultFeature = 0xFFFFFFFF;
sl@0
    24
sl@0
    25
static const LETag emptyTag = 0x00000000;
sl@0
    26
sl@0
    27
sl@0
    28
le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable,
sl@0
    29
    GlyphIterator *glyphIterator, const LEFontInstance *fontInstance,
sl@0
    30
    LEErrorCode& success) const
sl@0
    31
{
sl@0
    32
    if (LE_FAILURE(success)) {
sl@0
    33
        return 0;
sl@0
    34
    }
sl@0
    35
sl@0
    36
    le_uint16 lookupType = SWAPW(lookupTable->lookupType);
sl@0
    37
    le_uint16 subtableCount = SWAPW(lookupTable->subTableCount);
sl@0
    38
    le_int32 startPosition = glyphIterator->getCurrStreamPosition();
sl@0
    39
    le_uint32 delta;
sl@0
    40
sl@0
    41
    for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) {
sl@0
    42
        const LookupSubtable *lookupSubtable = lookupTable->getLookupSubtable(subtable);
sl@0
    43
sl@0
    44
        delta = applySubtable(lookupSubtable, lookupType, glyphIterator,
sl@0
    45
            fontInstance, success);
sl@0
    46
sl@0
    47
        if (delta > 0 || LE_FAILURE(success)) {
sl@0
    48
            return 1;
sl@0
    49
        }
sl@0
    50
sl@0
    51
        glyphIterator->setCurrStreamPosition(startPosition);
sl@0
    52
    }
sl@0
    53
sl@0
    54
    return 1;
sl@0
    55
}
sl@0
    56
sl@0
    57
le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
sl@0
    58
                              le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
sl@0
    59
                              const LEFontInstance *fontInstance, LEErrorCode& success) const
sl@0
    60
{
sl@0
    61
    if (LE_FAILURE(success)) {
sl@0
    62
        return 0;
sl@0
    63
    }
sl@0
    64
sl@0
    65
    le_int32 glyphCount = glyphStorage.getGlyphCount();
sl@0
    66
sl@0
    67
    if (lookupSelectArray == NULL) {
sl@0
    68
        return glyphCount;
sl@0
    69
    }
sl@0
    70
sl@0
    71
    GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments,
sl@0
    72
                                rightToLeft, 0, 0, glyphDefinitionTableHeader);
sl@0
    73
    le_int32 newGlyphCount = glyphCount;
sl@0
    74
sl@0
    75
    for (le_uint16 order = 0; order < lookupOrderCount; order += 1) {
sl@0
    76
        le_uint16 lookup = lookupOrderArray[order];
sl@0
    77
        LETag selectTag = lookupSelectArray[lookup];
sl@0
    78
sl@0
    79
        if (selectTag != notSelected) {
sl@0
    80
            const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup);
sl@0
    81
            le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
sl@0
    82
            
sl@0
    83
            glyphIterator.reset(lookupFlags, selectTag);
sl@0
    84
sl@0
    85
            while (glyphIterator.findFeatureTag()) {
sl@0
    86
                le_uint32 delta = 1;
sl@0
    87
sl@0
    88
                while (glyphIterator.next(delta)) {
sl@0
    89
                    delta = applyLookupTable(lookupTable, &glyphIterator, fontInstance, success);
sl@0
    90
                    if (LE_FAILURE(success)) {
sl@0
    91
                        return 0;
sl@0
    92
                    }
sl@0
    93
                }
sl@0
    94
            }
sl@0
    95
sl@0
    96
            newGlyphCount = glyphIterator.applyInsertions();
sl@0
    97
        }
sl@0
    98
    }
sl@0
    99
sl@0
   100
    return newGlyphCount;
sl@0
   101
}
sl@0
   102
sl@0
   103
le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
sl@0
   104
    const LEFontInstance *fontInstance, LEErrorCode& success) const
sl@0
   105
{
sl@0
   106
    if (LE_FAILURE(success)) {
sl@0
   107
        return 0;
sl@0
   108
    }
sl@0
   109
sl@0
   110
    const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
sl@0
   111
    le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
sl@0
   112
    GlyphIterator tempIterator(*glyphIterator, lookupFlags);
sl@0
   113
    le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success);
sl@0
   114
sl@0
   115
    return delta;
sl@0
   116
}
sl@0
   117
sl@0
   118
le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, LETag featureTag, le_int32 order)
sl@0
   119
{
sl@0
   120
    le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0;
sl@0
   121
    le_int32  store = order;
sl@0
   122
sl@0
   123
    for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) {
sl@0
   124
        le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]);
sl@0
   125
sl@0
   126
        if (lookupSelectArray[lookupListIndex] == notSelected) { 
sl@0
   127
            lookupSelectArray[lookupListIndex] = featureTag;
sl@0
   128
            lookupOrderArray[store++]   = lookupListIndex;
sl@0
   129
        }
sl@0
   130
    }
sl@0
   131
sl@0
   132
    return store - order;
sl@0
   133
}
sl@0
   134
sl@0
   135
LookupProcessor::LookupProcessor(const char *baseAddress,
sl@0
   136
        Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
sl@0
   137
        LETag scriptTag, LETag languageTag, const LETag *featureOrder)
sl@0
   138
    : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL),
sl@0
   139
      requiredFeatureTag(notSelected), lookupOrderArray(NULL), lookupOrderCount(0)
sl@0
   140
{
sl@0
   141
    const ScriptListTable *scriptListTable = NULL;
sl@0
   142
    const LangSysTable *langSysTable = NULL;
sl@0
   143
    le_uint16 featureCount = 0;
sl@0
   144
    le_uint16 lookupListCount = 0;
sl@0
   145
    le_uint16 requiredFeatureIndex;
sl@0
   146
sl@0
   147
    if (scriptListOffset != 0) {
sl@0
   148
        scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset);
sl@0
   149
        langSysTable = scriptListTable->findLanguage(scriptTag, languageTag);
sl@0
   150
sl@0
   151
        if (langSysTable != 0) {
sl@0
   152
            featureCount = SWAPW(langSysTable->featureCount);
sl@0
   153
        }
sl@0
   154
    }
sl@0
   155
sl@0
   156
    if (featureListOffset != 0) {
sl@0
   157
        featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset);
sl@0
   158
    }
sl@0
   159
sl@0
   160
    if (lookupListOffset != 0) {
sl@0
   161
        lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset);
sl@0
   162
        lookupListCount = SWAPW(lookupListTable->lookupCount);
sl@0
   163
    }
sl@0
   164
    
sl@0
   165
    if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL ||
sl@0
   166
        featureCount == 0 || lookupListCount == 0) {
sl@0
   167
        return;
sl@0
   168
    }
sl@0
   169
 
sl@0
   170
    requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex);
sl@0
   171
sl@0
   172
    lookupSelectArray = LE_NEW_ARRAY(LETag, lookupListCount);
sl@0
   173
    if (!lookupSelectArray)
sl@0
   174
    	return;
sl@0
   175
sl@0
   176
    for (int i = 0; i < lookupListCount; i += 1) {
sl@0
   177
        lookupSelectArray[i] = notSelected;
sl@0
   178
    }
sl@0
   179
sl@0
   180
    le_int32 count, order = 0;
sl@0
   181
    const FeatureTable *featureTable = 0;
sl@0
   182
    LETag featureTag;
sl@0
   183
sl@0
   184
    lookupOrderArray = LE_NEW_ARRAY(le_uint16, lookupListCount);
sl@0
   185
    if (!lookupOrderArray)
sl@0
   186
    	return;
sl@0
   187
sl@0
   188
    if (requiredFeatureIndex != 0xFFFF) {
sl@0
   189
        featureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &featureTag);
sl@0
   190
        order += selectLookups(featureTable, defaultFeature, order);
sl@0
   191
    }
sl@0
   192
sl@0
   193
    if (featureOrder != NULL) {
sl@0
   194
        if (order > 1) {
sl@0
   195
            OpenTypeUtilities::sort(lookupOrderArray, order);
sl@0
   196
        }
sl@0
   197
sl@0
   198
        for (le_int32 tag = 0; featureOrder[tag] != emptyTag; tag += 1) {
sl@0
   199
            featureTag = featureOrder[tag];
sl@0
   200
            count = 0;
sl@0
   201
sl@0
   202
            for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
sl@0
   203
                le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
sl@0
   204
sl@0
   205
                featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
sl@0
   206
sl@0
   207
                if (featureTag == featureOrder[tag]) {
sl@0
   208
                    count += selectLookups(featureTable, featureTag, order + count);
sl@0
   209
                }
sl@0
   210
            }
sl@0
   211
sl@0
   212
            if (count > 1) {
sl@0
   213
                OpenTypeUtilities::sort(&lookupOrderArray[order], count);
sl@0
   214
            }
sl@0
   215
sl@0
   216
            order += count;
sl@0
   217
        }
sl@0
   218
    } else {
sl@0
   219
        for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
sl@0
   220
            le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
sl@0
   221
 
sl@0
   222
            // don't add the required feature to the list more than once...
sl@0
   223
            if (featureIndex == requiredFeatureIndex) {
sl@0
   224
                continue;
sl@0
   225
            }
sl@0
   226
sl@0
   227
            featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
sl@0
   228
            count = selectLookups(featureTable, featureTag, order);
sl@0
   229
            order += count;
sl@0
   230
        }
sl@0
   231
sl@0
   232
        if (order > 1) {
sl@0
   233
            OpenTypeUtilities::sort(lookupOrderArray, order);
sl@0
   234
        }
sl@0
   235
    }
sl@0
   236
sl@0
   237
    lookupOrderCount = order;
sl@0
   238
}
sl@0
   239
sl@0
   240
LookupProcessor::LookupProcessor()
sl@0
   241
{
sl@0
   242
    lookupOrderArray = 0;
sl@0
   243
    lookupSelectArray = 0;
sl@0
   244
}
sl@0
   245
sl@0
   246
le_bool LookupProcessor::isBogus()
sl@0
   247
{
sl@0
   248
    return lookupSelectArray && lookupSelectArray? FALSE : TRUE;
sl@0
   249
}
sl@0
   250
sl@0
   251
LookupProcessor::~LookupProcessor()
sl@0
   252
{
sl@0
   253
    LE_DELETE_ARRAY(lookupOrderArray);
sl@0
   254
    LE_DELETE_ARRAY(lookupSelectArray);
sl@0
   255
}
sl@0
   256
sl@0
   257
U_NAMESPACE_END