os/textandloc/fontservices/textshaperplugin/IcuSource/layout/LayoutEngine.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
 *
sl@0
     4
 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
sl@0
     5
 *
sl@0
     6
 */
sl@0
     7
sl@0
     8
#include "LETypes.h"
sl@0
     9
#include "LEScripts.h"
sl@0
    10
#include "LELanguages.h"
sl@0
    11
sl@0
    12
#include "LayoutEngine.h"
sl@0
    13
#include "ArabicLayoutEngine.h"
sl@0
    14
#include "CanonShaping.h"
sl@0
    15
#include "HanLayoutEngine.h"
sl@0
    16
#include "IndicLayoutEngine.h"
sl@0
    17
#include "KhmerLayoutEngine.h"
sl@0
    18
#include "ThaiLayoutEngine.h"
sl@0
    19
#include "GXLayoutEngine.h"
sl@0
    20
#include "ScriptAndLanguageTags.h"
sl@0
    21
#include "CharSubstitutionFilter.h"
sl@0
    22
sl@0
    23
#include "LEGlyphStorage.h"
sl@0
    24
sl@0
    25
#include "OpenTypeUtilities.h"
sl@0
    26
#include "GlyphSubstitutionTables.h"
sl@0
    27
#include "MorphTables.h"
sl@0
    28
sl@0
    29
#include "DefaultCharMapper.h"
sl@0
    30
sl@0
    31
#include "KernTable.h"
sl@0
    32
sl@0
    33
U_NAMESPACE_BEGIN
sl@0
    34
sl@0
    35
#define ARRAY_SIZE(array) (sizeof array  / sizeof array[0])
sl@0
    36
sl@0
    37
const LEUnicode32 DefaultCharMapper::controlChars[] = {
sl@0
    38
    0x0009, 0x000A, 0x000D,
sl@0
    39
    /*0x200C, 0x200D,*/ 0x200E, 0x200F,
sl@0
    40
    0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
sl@0
    41
    0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
sl@0
    42
};
sl@0
    43
sl@0
    44
const le_int32 DefaultCharMapper::controlCharsCount = ARRAY_SIZE(controlChars);
sl@0
    45
sl@0
    46
const LEUnicode32 DefaultCharMapper::mirroredChars[] = {
sl@0
    47
    0x0028, 0x0029, // ascii paired punctuation
sl@0
    48
    0x003c, 0x003e,
sl@0
    49
    0x005b, 0x005d,
sl@0
    50
    0x007b, 0x007d,
sl@0
    51
    0x2045, 0x2046, // math symbols (not complete)
sl@0
    52
    0x207d, 0x207e,
sl@0
    53
    0x208d, 0x208e,
sl@0
    54
    0x2264, 0x2265,
sl@0
    55
    0x3008, 0x3009, // chinese paired punctuation
sl@0
    56
    0x300a, 0x300b,
sl@0
    57
    0x300c, 0x300d,
sl@0
    58
    0x300e, 0x300f,
sl@0
    59
    0x3010, 0x3011,
sl@0
    60
    0x3014, 0x3015,
sl@0
    61
    0x3016, 0x3017,
sl@0
    62
    0x3018, 0x3019,
sl@0
    63
    0x301a, 0x301b
sl@0
    64
};
sl@0
    65
sl@0
    66
const le_int32 DefaultCharMapper::mirroredCharsCount = ARRAY_SIZE(mirroredChars);
sl@0
    67
sl@0
    68
LEUnicode32 DefaultCharMapper::mapChar(LEUnicode32 ch) const
sl@0
    69
{
sl@0
    70
    if (fFilterControls) {
sl@0
    71
        le_int32 index = OpenTypeUtilities::search((le_uint32)ch, (le_uint32 *)controlChars, controlCharsCount);
sl@0
    72
sl@0
    73
        if (controlChars[index] == ch) {
sl@0
    74
            return 0xFFFF;
sl@0
    75
        }
sl@0
    76
    }
sl@0
    77
sl@0
    78
    if (fMirror) {
sl@0
    79
        le_int32 index = OpenTypeUtilities::search((le_uint32) ch, (le_uint32 *)mirroredChars, mirroredCharsCount);
sl@0
    80
sl@0
    81
        if (mirroredChars[index] == ch) {
sl@0
    82
            le_int32 mirrorOffset = ((index & 1) == 0) ? 1 : -1;
sl@0
    83
sl@0
    84
            return mirroredChars[index + mirrorOffset];
sl@0
    85
        }
sl@0
    86
    }
sl@0
    87
sl@0
    88
    return ch;
sl@0
    89
}
sl@0
    90
sl@0
    91
// This is here to get it out of LEGlyphFilter.h.
sl@0
    92
// No particular reason to put it here, other than
sl@0
    93
// this is a good central location...
sl@0
    94
LEGlyphFilter::~LEGlyphFilter()
sl@0
    95
{
sl@0
    96
    // nothing to do
sl@0
    97
}
sl@0
    98
sl@0
    99
CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
sl@0
   100
  : fFontInstance(fontInstance)
sl@0
   101
{
sl@0
   102
    // nothing to do
sl@0
   103
}
sl@0
   104
sl@0
   105
CharSubstitutionFilter::~CharSubstitutionFilter()
sl@0
   106
{
sl@0
   107
    // nothing to do
sl@0
   108
}
sl@0
   109
sl@0
   110
sl@0
   111
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LayoutEngine)
sl@0
   112
sl@0
   113
static const LETag emptyTag = 0x00000000;
sl@0
   114
sl@0
   115
static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG;
sl@0
   116
sl@0
   117
static const LETag canonFeatures[] = {ccmpFeatureTag, emptyTag};
sl@0
   118
sl@0
   119
LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags)
sl@0
   120
  : fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode),
sl@0
   121
    fTypoFlags(typoFlags), fGidOfRA(0)
sl@0
   122
{
sl@0
   123
    fGlyphStorage = new LEGlyphStorage();
sl@0
   124
}
sl@0
   125
sl@0
   126
le_bool LayoutEngine::isBogus()
sl@0
   127
{
sl@0
   128
    return fGlyphStorage? FALSE : TRUE;
sl@0
   129
}
sl@0
   130
sl@0
   131
le_int32 LayoutEngine::getGlyphCount() const
sl@0
   132
{
sl@0
   133
    return fGlyphStorage->getGlyphCount();
sl@0
   134
}
sl@0
   135
sl@0
   136
void LayoutEngine::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
sl@0
   137
{
sl@0
   138
    fGlyphStorage->getCharIndices(charIndices, indexBase, success);
sl@0
   139
}
sl@0
   140
sl@0
   141
void LayoutEngine::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
sl@0
   142
{
sl@0
   143
    fGlyphStorage->getCharIndices(charIndices, success);
sl@0
   144
}
sl@0
   145
sl@0
   146
// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
sl@0
   147
void LayoutEngine::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
sl@0
   148
{
sl@0
   149
    fGlyphStorage->getGlyphs(glyphs, extraBits, success);
sl@0
   150
}
sl@0
   151
sl@0
   152
void LayoutEngine::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
sl@0
   153
{
sl@0
   154
    fGlyphStorage->getGlyphs(glyphs, success);
sl@0
   155
}
sl@0
   156
sl@0
   157
sl@0
   158
void LayoutEngine::getGlyphPositions(float positions[], LEErrorCode &success) const
sl@0
   159
{
sl@0
   160
    fGlyphStorage->getGlyphPositions(positions, success);
sl@0
   161
}
sl@0
   162
sl@0
   163
void LayoutEngine::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
sl@0
   164
{
sl@0
   165
    fGlyphStorage->getGlyphPosition(glyphIndex, x, y, success);
sl@0
   166
}
sl@0
   167
sl@0
   168
le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
sl@0
   169
                LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
sl@0
   170
{
sl@0
   171
    if (LE_FAILURE(success)) {
sl@0
   172
        return 0;
sl@0
   173
    }
sl@0
   174
sl@0
   175
    if (offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
sl@0
   176
        success = LE_ILLEGAL_ARGUMENT_ERROR;
sl@0
   177
        return 0;
sl@0
   178
    }
sl@0
   179
sl@0
   180
    const GlyphSubstitutionTableHeader *canonGSUBTable = (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
sl@0
   181
    LETag scriptTag  = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
sl@0
   182
    LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
sl@0
   183
    le_int32 i, dir = 1, out = 0, outCharCount = count;
sl@0
   184
sl@0
   185
    if (canonGSUBTable->coversScript(scriptTag)) {
sl@0
   186
        CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
sl@0
   187
        if (!substitutionFilter) {
sl@0
   188
            success = LE_MEMORY_ALLOCATION_ERROR;
sl@0
   189
            return 0;
sl@0
   190
        }
sl@0
   191
sl@0
   192
		const LEUnicode *inChars = &chars[offset];
sl@0
   193
		LEUnicode *reordered = NULL;
sl@0
   194
sl@0
   195
		// This is the cheapest way to get mark reordering only for Hebrew.
sl@0
   196
		// We could just do the mark reordering for all scripts, but most
sl@0
   197
		// of them probably don't need it...
sl@0
   198
		if (fScriptCode == hebrScriptCode) {
sl@0
   199
			reordered = LE_NEW_ARRAY(LEUnicode, count);
sl@0
   200
sl@0
   201
			if (reordered == NULL) {
sl@0
   202
				success = LE_MEMORY_ALLOCATION_ERROR;
sl@0
   203
				delete substitutionFilter;
sl@0
   204
				return 0;
sl@0
   205
			}
sl@0
   206
sl@0
   207
			CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, glyphStorage);
sl@0
   208
			inChars = reordered;
sl@0
   209
		}
sl@0
   210
sl@0
   211
        glyphStorage.allocateGlyphArray(count, rightToLeft, success);
sl@0
   212
        glyphStorage.allocateAuxData(success);
sl@0
   213
sl@0
   214
        if (LE_FAILURE(success)) {
sl@0
   215
            delete substitutionFilter;
sl@0
   216
            return 0;
sl@0
   217
        }
sl@0
   218
sl@0
   219
        if (rightToLeft) {
sl@0
   220
            out = count - 1;
sl@0
   221
            dir = -1;
sl@0
   222
        }
sl@0
   223
sl@0
   224
        for (i = 0; i < count; i += 1, out += dir) {
sl@0
   225
            glyphStorage[out] = (LEGlyphID) inChars[i];
sl@0
   226
            glyphStorage.setAuxData(out, (void *) canonFeatures, success);
sl@0
   227
        }
sl@0
   228
sl@0
   229
		if (reordered != NULL) {
sl@0
   230
			LE_DELETE_ARRAY(reordered);
sl@0
   231
		}
sl@0
   232
sl@0
   233
        outCharCount = canonGSUBTable->process(glyphStorage, rightToLeft,
sl@0
   234
            scriptTag, langSysTag, NULL, success, substitutionFilter, NULL);
sl@0
   235
sl@0
   236
        if (LE_FAILURE(success)) {
sl@0
   237
            delete substitutionFilter;
sl@0
   238
            return 0;
sl@0
   239
        }
sl@0
   240
sl@0
   241
        out = (rightToLeft? count - 1 : 0);
sl@0
   242
sl@0
   243
        outChars = LE_NEW_ARRAY(LEUnicode, outCharCount);
sl@0
   244
        if (!outChars) {
sl@0
   245
            delete substitutionFilter;
sl@0
   246
            success = LE_MEMORY_ALLOCATION_ERROR;
sl@0
   247
            return 0;
sl@0
   248
        }
sl@0
   249
        for (i = 0; i < outCharCount; i += 1, out += dir) {
sl@0
   250
            outChars[out] = (LEUnicode) LE_GET_GLYPH(glyphStorage[i]);
sl@0
   251
        }
sl@0
   252
sl@0
   253
        delete substitutionFilter;
sl@0
   254
    }
sl@0
   255
sl@0
   256
    return outCharCount;
sl@0
   257
}
sl@0
   258
sl@0
   259
le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
sl@0
   260
                                            LEGlyphStorage &glyphStorage, LEErrorCode &success)
sl@0
   261
{
sl@0
   262
    if (LE_FAILURE(success)) {
sl@0
   263
        return 0;
sl@0
   264
    }
sl@0
   265
sl@0
   266
    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
sl@0
   267
        success = LE_ILLEGAL_ARGUMENT_ERROR;
sl@0
   268
        return 0;
sl@0
   269
    }
sl@0
   270
sl@0
   271
    LEUnicode *outChars = NULL;
sl@0
   272
    le_int32 outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success);
sl@0
   273
sl@0
   274
    if (outChars != NULL) {
sl@0
   275
        mapCharsToGlyphs(outChars, 0, outCharCount, rightToLeft, rightToLeft, glyphStorage, success);
sl@0
   276
        LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
sl@0
   277
    } else {
sl@0
   278
        mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
sl@0
   279
    }
sl@0
   280
sl@0
   281
    return glyphStorage.getGlyphCount();
sl@0
   282
}
sl@0
   283
sl@0
   284
// Input: glyphs
sl@0
   285
// Output: positions
sl@0
   286
void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y, LEErrorCode &success)
sl@0
   287
{
sl@0
   288
    if (LE_FAILURE(success)) {
sl@0
   289
        return;
sl@0
   290
    }
sl@0
   291
sl@0
   292
    glyphStorage.allocatePositions(success);
sl@0
   293
sl@0
   294
    if (LE_FAILURE(success)) {
sl@0
   295
        return;
sl@0
   296
    }
sl@0
   297
sl@0
   298
    le_int32 i, glyphCount = glyphStorage.getGlyphCount();
sl@0
   299
sl@0
   300
    for (i = 0; i < glyphCount; i += 1) {
sl@0
   301
        LEPoint advance;
sl@0
   302
sl@0
   303
        glyphStorage.setPosition(i, x, y, success);
sl@0
   304
sl@0
   305
        fFontInstance->getGlyphAdvance(glyphStorage[i], advance);
sl@0
   306
        x += advance.fX;
sl@0
   307
        y += advance.fY;
sl@0
   308
    }
sl@0
   309
sl@0
   310
    glyphStorage.setPosition(glyphCount, x, y, success);
sl@0
   311
}
sl@0
   312
sl@0
   313
void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/,
sl@0
   314
                                        LEGlyphStorage &glyphStorage, LEErrorCode &success)
sl@0
   315
{
sl@0
   316
    if (LE_FAILURE(success)) {
sl@0
   317
        return;
sl@0
   318
    }
sl@0
   319
sl@0
   320
    if (chars == NULL || offset < 0 || count < 0) {
sl@0
   321
        success = LE_ILLEGAL_ARGUMENT_ERROR;
sl@0
   322
        return;
sl@0
   323
    }
sl@0
   324
sl@0
   325
    if (fTypoFlags & 0x1) { /* kerning enabled */
sl@0
   326
      static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
sl@0
   327
sl@0
   328
      KernTable kt(fFontInstance, getFontTable(kernTableTag));
sl@0
   329
      kt.process(glyphStorage);
sl@0
   330
    }
sl@0
   331
sl@0
   332
    // default is no adjustments
sl@0
   333
    return;
sl@0
   334
}
sl@0
   335
sl@0
   336
void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
sl@0
   337
{
sl@0
   338
    float xAdjust = 0;
sl@0
   339
    le_int32 p, glyphCount = glyphStorage.getGlyphCount();
sl@0
   340
sl@0
   341
    if (LE_FAILURE(success)) {
sl@0
   342
        return;
sl@0
   343
    }
sl@0
   344
sl@0
   345
    if (markFilter == NULL) {
sl@0
   346
        success = LE_ILLEGAL_ARGUMENT_ERROR;
sl@0
   347
        return;
sl@0
   348
    }
sl@0
   349
sl@0
   350
    float ignore, prev;
sl@0
   351
sl@0
   352
    glyphStorage.getGlyphPosition(0, prev, ignore, success);
sl@0
   353
sl@0
   354
    for (p = 0; p < glyphCount; p += 1) {
sl@0
   355
        float next, xAdvance;
sl@0
   356
        
sl@0
   357
        glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
sl@0
   358
sl@0
   359
        xAdvance = next - prev;
sl@0
   360
        glyphStorage.adjustPosition(p, xAdjust, 0, success);
sl@0
   361
sl@0
   362
        if (markFilter->accept(glyphStorage[p])) {
sl@0
   363
            xAdjust -= xAdvance;
sl@0
   364
        }
sl@0
   365
sl@0
   366
        prev = next;
sl@0
   367
    }
sl@0
   368
sl@0
   369
    glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
sl@0
   370
}
sl@0
   371
sl@0
   372
void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
sl@0
   373
{
sl@0
   374
    float xAdjust = 0;
sl@0
   375
    le_int32 c = 0, direction = 1, p;
sl@0
   376
    le_int32 glyphCount = glyphStorage.getGlyphCount();
sl@0
   377
sl@0
   378
    if (LE_FAILURE(success)) {
sl@0
   379
        return;
sl@0
   380
    }
sl@0
   381
sl@0
   382
    if (markFilter == NULL) {
sl@0
   383
        success = LE_ILLEGAL_ARGUMENT_ERROR;
sl@0
   384
        return;
sl@0
   385
    }
sl@0
   386
sl@0
   387
    if (reverse) {
sl@0
   388
        c = glyphCount - 1;
sl@0
   389
        direction = -1;
sl@0
   390
    }
sl@0
   391
sl@0
   392
    float ignore, prev;
sl@0
   393
sl@0
   394
    glyphStorage.getGlyphPosition(0, prev, ignore, success);
sl@0
   395
sl@0
   396
    for (p = 0; p < charCount; p += 1, c += direction) {
sl@0
   397
        float next, xAdvance;
sl@0
   398
        
sl@0
   399
        glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
sl@0
   400
sl@0
   401
        xAdvance = next - prev;
sl@0
   402
        glyphStorage.adjustPosition(p, xAdjust, 0, success);
sl@0
   403
sl@0
   404
        if (markFilter->accept(chars[c])) {
sl@0
   405
            xAdjust -= xAdvance;
sl@0
   406
        }
sl@0
   407
sl@0
   408
        prev = next;
sl@0
   409
    }
sl@0
   410
sl@0
   411
    glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
sl@0
   412
}
sl@0
   413
sl@0
   414
const void *LayoutEngine::getFontTable(LETag tableTag) const
sl@0
   415
{
sl@0
   416
    return fFontInstance->getFontTable(tableTag);
sl@0
   417
}
sl@0
   418
sl@0
   419
void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
sl@0
   420
                                    LEGlyphStorage &glyphStorage, LEErrorCode &success)
sl@0
   421
{
sl@0
   422
    if (LE_FAILURE(success)) {
sl@0
   423
        return;
sl@0
   424
    }
sl@0
   425
sl@0
   426
    glyphStorage.allocateGlyphArray(count, reverse, success);
sl@0
   427
sl@0
   428
    DefaultCharMapper charMapper(TRUE, mirror);
sl@0
   429
sl@0
   430
    fFontInstance->mapCharsToGlyphs(chars, offset, count, reverse, &charMapper, glyphStorage);
sl@0
   431
}
sl@0
   432
sl@0
   433
// Input: characters, font?
sl@0
   434
// Output: glyphs, positions, char indices
sl@0
   435
// Returns: number of glyphs
sl@0
   436
le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
sl@0
   437
                              float x, float y, LEErrorCode &success)
sl@0
   438
{
sl@0
   439
    if (LE_FAILURE(success)) {
sl@0
   440
        return 0;
sl@0
   441
    }
sl@0
   442
sl@0
   443
    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
sl@0
   444
        success = LE_ILLEGAL_ARGUMENT_ERROR;
sl@0
   445
        return 0;
sl@0
   446
    }
sl@0
   447
sl@0
   448
    // 1922 mlyl: get the glyph ID of RAKAR -->
sl@0
   449
    const LEUnicode RAKAR[] = {0xFFFF, 0xD15, 0xD4D, 0xD30, 0xFFFF};
sl@0
   450
    if (fGidOfRA == 0 && mlymScriptCode == fScriptCode) {
sl@0
   451
    	fGidOfRA = -1;  // 0xFFFFFFFF
sl@0
   452
    	TInt noOfGlyphs = layoutChars(
sl@0
   453
    			RAKAR, 		// chars - the input character context
sl@0
   454
    			1,			// the offset of the first character to process	
sl@0
   455
    			3,			// count - the number of characters to process	// offset
sl@0
   456
    			5, 			// max - the number of characters in the input context	// size of text
sl@0
   457
    			FALSE, 		// rightToLeft - TRUE if the characters are in a right to left directional run
sl@0
   458
    			0, 			// start X
sl@0
   459
    			0, 			// start Y
sl@0
   460
    			success);	// result code
sl@0
   461
    	
sl@0
   462
    	if (!LE_FAILURE(success)) {
sl@0
   463
    		fGidOfRA = (*fGlyphStorage)[1];
sl@0
   464
    		(*fGlyphStorage).reset();
sl@0
   465
    	}
sl@0
   466
    }
sl@0
   467
    // <-- 1922 mlyl
sl@0
   468
    
sl@0
   469
    le_int32 glyphCount;
sl@0
   470
    
sl@0
   471
    glyphCount = computeGlyphs(chars, offset, count, max, rightToLeft, *fGlyphStorage, success);
sl@0
   472
    
sl@0
   473
    // 1922 mlyl: put RAKAR left of the preceding glyph -->
sl@0
   474
    if (fGidOfRA != 0 && fGidOfRA != -1 && mlymScriptCode == fScriptCode) {
sl@0
   475
    	fGlyphStorage->forMlylRakar(fGidOfRA);
sl@0
   476
    }
sl@0
   477
    // <-- 1922 mlyl
sl@0
   478
    
sl@0
   479
    positionGlyphs(*fGlyphStorage, x, y, success);
sl@0
   480
    adjustGlyphPositions(chars, offset, count, rightToLeft, *fGlyphStorage, success);
sl@0
   481
sl@0
   482
    return glyphCount;
sl@0
   483
}
sl@0
   484
sl@0
   485
void LayoutEngine::reset()
sl@0
   486
{
sl@0
   487
    fGlyphStorage->reset();
sl@0
   488
}
sl@0
   489
    
sl@0
   490
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
sl@0
   491
{
sl@0
   492
  // 3 -> kerning and ligatures
sl@0
   493
  return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, 3, success);
sl@0
   494
}
sl@0
   495
    
sl@0
   496
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
sl@0
   497
{
sl@0
   498
    static const le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
sl@0
   499
    static const le_uint32 mortTableTag = LE_MORT_TABLE_TAG;
sl@0
   500
sl@0
   501
    if (LE_FAILURE(success)) {
sl@0
   502
        return NULL;
sl@0
   503
    }
sl@0
   504
sl@0
   505
    const GlyphSubstitutionTableHeader *gsubTable = (const GlyphSubstitutionTableHeader *) fontInstance->getFontTable(gsubTableTag);
sl@0
   506
    LayoutEngine *result = NULL;
sl@0
   507
    LETag scriptTag   = 0x00000000;
sl@0
   508
    LETag languageTag = 0x00000000;
sl@0
   509
sl@0
   510
    if (gsubTable != NULL && gsubTable->coversScript(scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode))) {
sl@0
   511
        switch (scriptCode) {
sl@0
   512
        case bengScriptCode:
sl@0
   513
        case devaScriptCode:
sl@0
   514
        case gujrScriptCode:
sl@0
   515
        case kndaScriptCode:
sl@0
   516
        case mlymScriptCode:
sl@0
   517
        case oryaScriptCode:
sl@0
   518
        case guruScriptCode:
sl@0
   519
        case tamlScriptCode:
sl@0
   520
        case teluScriptCode:
sl@0
   521
            result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
sl@0
   522
            break;
sl@0
   523
sl@0
   524
        case arabScriptCode:
sl@0
   525
            result = new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
sl@0
   526
            break;
sl@0
   527
sl@0
   528
        case haniScriptCode:
sl@0
   529
            languageTag = OpenTypeLayoutEngine::getLangSysTag(languageCode);
sl@0
   530
sl@0
   531
            switch (languageCode) {
sl@0
   532
            case korLanguageCode:
sl@0
   533
            case janLanguageCode:
sl@0
   534
            case zhtLanguageCode:
sl@0
   535
            case zhsLanguageCode:
sl@0
   536
                if (gsubTable->coversScriptAndLanguage(scriptTag, languageTag, TRUE)) {
sl@0
   537
                    result = new HanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
sl@0
   538
                    break;
sl@0
   539
                }
sl@0
   540
sl@0
   541
                // note: falling through to default case.
sl@0
   542
            default:
sl@0
   543
                result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
sl@0
   544
                break;
sl@0
   545
            }
sl@0
   546
sl@0
   547
            break;
sl@0
   548
sl@0
   549
        case khmrScriptCode:
sl@0
   550
            result = new KhmerOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
sl@0
   551
            break;
sl@0
   552
sl@0
   553
        default:
sl@0
   554
            result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
sl@0
   555
            break;
sl@0
   556
        }
sl@0
   557
    } else {
sl@0
   558
        const MorphTableHeader *morphTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
sl@0
   559
sl@0
   560
        if (morphTable != NULL) {
sl@0
   561
            result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, morphTable);
sl@0
   562
        } else {
sl@0
   563
            switch (scriptCode) {
sl@0
   564
            case bengScriptCode:
sl@0
   565
            case devaScriptCode:
sl@0
   566
            case gujrScriptCode:
sl@0
   567
            case kndaScriptCode:
sl@0
   568
            case mlymScriptCode:
sl@0
   569
            case oryaScriptCode:
sl@0
   570
            case guruScriptCode:
sl@0
   571
            case tamlScriptCode:
sl@0
   572
            case teluScriptCode:
sl@0
   573
            {
sl@0
   574
                result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
sl@0
   575
                break;
sl@0
   576
            }
sl@0
   577
sl@0
   578
            case arabScriptCode:
sl@0
   579
            //case hebrScriptCode:
sl@0
   580
                result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
sl@0
   581
                break;
sl@0
   582
sl@0
   583
            //case hebrScriptCode:
sl@0
   584
            //    return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
sl@0
   585
sl@0
   586
            case thaiScriptCode:
sl@0
   587
                result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
sl@0
   588
                break;
sl@0
   589
sl@0
   590
            default:
sl@0
   591
                result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
sl@0
   592
                break;
sl@0
   593
            }
sl@0
   594
        }
sl@0
   595
    }
sl@0
   596
sl@0
   597
    if (result && result->isBogus()) {
sl@0
   598
        delete result;
sl@0
   599
        result = NULL;
sl@0
   600
    }
sl@0
   601
    if (result == NULL) {
sl@0
   602
        success = LE_MEMORY_ALLOCATION_ERROR;
sl@0
   603
    }
sl@0
   604
sl@0
   605
    return result;
sl@0
   606
}
sl@0
   607
sl@0
   608
LayoutEngine::~LayoutEngine() {
sl@0
   609
    delete fGlyphStorage;
sl@0
   610
}
sl@0
   611
sl@0
   612
U_NAMESPACE_END