LayoutEngine.cpp 24.0 KB
Newer Older
D
duke 已提交
1 2 3 4 5
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
6
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
7
 * particular file as subject to the "Classpath" exception as provided
8
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
20 21 22
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
23 24 25
 *
 */

26

D
duke 已提交
27 28 29 30 31 32 33 34 35
/*
 *
 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
 *
 */

#include "LETypes.h"
#include "LEScripts.h"
#include "LELanguages.h"
P
prr 已提交
36
#include "LESwaps.h"
D
duke 已提交
37 38 39 40 41

#include "LayoutEngine.h"
#include "ArabicLayoutEngine.h"
#include "CanonShaping.h"
#include "HanLayoutEngine.h"
S
srl 已提交
42
#include "HangulLayoutEngine.h"
D
duke 已提交
43 44 45
#include "IndicLayoutEngine.h"
#include "KhmerLayoutEngine.h"
#include "ThaiLayoutEngine.h"
S
srl 已提交
46
#include "TibetanLayoutEngine.h"
D
duke 已提交
47
#include "GXLayoutEngine.h"
P
prr 已提交
48 49
#include "GXLayoutEngine2.h"

D
duke 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62 63
#include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"

#include "LEGlyphStorage.h"

#include "OpenTypeUtilities.h"
#include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
#include "MorphTables.h"

#include "DefaultCharMapper.h"

#include "KernTable.h"

64 65
U_NAMESPACE_BEGIN

S
srl 已提交
66 67 68
/* Leave this copyright notice here! It needs to go somewhere in this library. */
static const char copyright[] = U_COPYRIGHT_STRING;

P
prr 已提交
69 70 71 72
/* TODO: remove these? */
const le_int32 LayoutEngine::kTypoFlagKern = LE_Kerning_FEATURE_FLAG;
const le_int32 LayoutEngine::kTypoFlagLiga = LE_Ligatures_FEATURE_FLAG;

D
duke 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
const LEUnicode32 DefaultCharMapper::controlChars[] = {
    0x0009, 0x000A, 0x000D,
    /*0x200C, 0x200D,*/ 0x200E, 0x200F,
    0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
    0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
};

const le_int32 DefaultCharMapper::controlCharsCount = LE_ARRAY_SIZE(controlChars);

const LEUnicode32 DefaultCharMapper::controlCharsZWJ[] = {
    0x0009, 0x000A, 0x000D,
    0x200C, 0x200D, 0x200E, 0x200F,
    0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
    0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
};

const le_int32 DefaultCharMapper::controlCharsZWJCount = LE_ARRAY_SIZE(controlCharsZWJ);

LEUnicode32 DefaultCharMapper::mapChar(LEUnicode32 ch) const
{
    if (fZWJ) {
        if (ch < 0x20) {
            if (ch == 0x0a || ch == 0x0d || ch == 0x09) {
                return 0xffff;
            }
        } else if (ch >= 0x200c && ch <= 0x206f) {
            le_int32 index = OpenTypeUtilities::search((le_uint32)ch,
                                                       (le_uint32 *)controlCharsZWJ,
                                                       controlCharsZWJCount);
            if (controlCharsZWJ[index] == ch) {
                return 0xffff;
            }
        }
        return ch; // note ZWJ bypasses fFilterControls and fMirror
    }

    if (fFilterControls) {
S
srl 已提交
110 111
        le_int32 index = OpenTypeUtilities::search((le_uint32)ch, (le_uint32 *)controlChars, controlCharsCount);

D
duke 已提交
112 113 114 115 116 117
        if (controlChars[index] == ch) {
            return 0xFFFF;
        }
    }

    if (fMirror) {
118
        le_int32 index = OpenTypeUtilities::search((le_uint32) ch, (le_uint32 *)DefaultCharMapper::mirroredChars, DefaultCharMapper::mirroredCharsCount);
D
duke 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

        if (mirroredChars[index] == ch) {
            return DefaultCharMapper::srahCderorrim[index];
        }
    }

    return ch;
}

// This is here to get it out of LEGlyphFilter.h.
// No particular reason to put it here, other than
// this is a good central location...
LEGlyphFilter::~LEGlyphFilter()
{
    // nothing to do
}

CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
  : fFontInstance(fontInstance)
{
    // nothing to do
}

CharSubstitutionFilter::~CharSubstitutionFilter()
{
    // nothing to do
}

S
srl 已提交
147 148 149
class CanonMarkFilter : public UMemory, public LEGlyphFilter
{
private:
P
prr 已提交
150
  const LEReferenceTo<GlyphClassDefinitionTable> classDefTable;
S
srl 已提交
151 152 153 154 155

    CanonMarkFilter(const CanonMarkFilter &other); // forbid copying of this class
    CanonMarkFilter &operator=(const CanonMarkFilter &other); // forbid copying of this class

public:
P
prr 已提交
156
    CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
S
srl 已提交
157 158
    virtual ~CanonMarkFilter();

P
prr 已提交
159
    virtual le_bool accept(LEGlyphID glyph, LEErrorCode &success) const;
S
srl 已提交
160 161
};

P
prr 已提交
162 163
CanonMarkFilter::CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
  : classDefTable(gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success))
S
srl 已提交
164 165 166 167 168 169 170 171
{
}

CanonMarkFilter::~CanonMarkFilter()
{
    // nothing to do?
}

P
prr 已提交
172
le_bool CanonMarkFilter::accept(LEGlyphID glyph, LEErrorCode &success) const
S
srl 已提交
173
{
P
prr 已提交
174 175 176
  le_int32 glyphClass = classDefTable->getGlyphClass(classDefTable, glyph, success);
  if(LE_FAILURE(success)) return false;
  return glyphClass != 0;
S
srl 已提交
177
}
178 179 180

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LayoutEngine)

D
duke 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193
#define ccmpFeatureTag  LE_CCMP_FEATURE_TAG

#define ccmpFeatureMask 0x80000000UL

#define canonFeatures (ccmpFeatureMask)

static const FeatureMap canonFeatureMap[] =
{
    {ccmpFeatureTag, ccmpFeatureMask}
};

static const le_int32 canonFeatureMapCount = LE_ARRAY_SIZE(canonFeatureMap);

S
srl 已提交
194 195 196 197 198
LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance,
                           le_int32 scriptCode,
                           le_int32 languageCode,
                           le_int32 typoFlags,
                           LEErrorCode &success)
199
  : fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode),
S
srl 已提交
200
    fTypoFlags(typoFlags), fFilterZeroWidth(TRUE)
D
duke 已提交
201
{
S
srl 已提交
202 203 204 205
    if (LE_FAILURE(success)) {
        return;
    }

D
duke 已提交
206
    fGlyphStorage = new LEGlyphStorage();
S
srl 已提交
207 208
    if (fGlyphStorage == NULL) {
        success = LE_MEMORY_ALLOCATION_ERROR;
P
prr 已提交
209
    }
D
duke 已提交
210 211 212 213 214 215 216
}

le_int32 LayoutEngine::getGlyphCount() const
{
    return fGlyphStorage->getGlyphCount();
}

217
void LayoutEngine::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
D
duke 已提交
218 219 220 221 222 223 224 225 226 227
{
    fGlyphStorage->getCharIndices(charIndices, indexBase, success);
}

void LayoutEngine::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
{
    fGlyphStorage->getCharIndices(charIndices, success);
}

// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
228
void LayoutEngine::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
D
duke 已提交
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
{
    fGlyphStorage->getGlyphs(glyphs, extraBits, success);
}

void LayoutEngine::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
{
    fGlyphStorage->getGlyphs(glyphs, success);
}


void LayoutEngine::getGlyphPositions(float positions[], LEErrorCode &success) const
{
    fGlyphStorage->getGlyphPositions(positions, success);
}

244
void LayoutEngine::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
D
duke 已提交
245 246 247 248
{
    fGlyphStorage->getGlyphPosition(glyphIndex, x, y, success);
}

249 250
le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
                LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
D
duke 已提交
251 252 253 254 255 256 257 258 259 260
{
    if (LE_FAILURE(success)) {
        return 0;
    }

    if (offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

P
prr 已提交
261
    if ((fTypoFlags & LE_NoCanon_FEATURE_FLAG) == 0) { // no canonical processing
262 263 264
      return count;
    }

P
prr 已提交
265 266 267
    LEReferenceTo<GlyphSubstitutionTableHeader> canonGSUBTable(LETableReference::kStaticData,
                                                               (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable,
                                                               CanonShaping::glyphSubstitutionTableLen);
D
duke 已提交
268 269 270 271
    LETag scriptTag  = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
    LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
    le_int32 i, dir = 1, out = 0, outCharCount = count;

P
prr 已提交
272
    if (canonGSUBTable->coversScript(canonGSUBTable,scriptTag, success) || LE_SUCCESS(success)) {
D
duke 已提交
273
        CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
S
srl 已提交
274 275 276 277 278
        if (substitutionFilter == NULL) {
            success = LE_MEMORY_ALLOCATION_ERROR;
            return 0;
        }

P
prr 已提交
279 280
        const LEUnicode *inChars = &chars[offset];
        LEUnicode *reordered = NULL;
S
srl 已提交
281 282 283 284 285 286 287 288
        LEGlyphStorage fakeGlyphStorage;

        fakeGlyphStorage.allocateGlyphArray(count, rightToLeft, success);

        if (LE_FAILURE(success)) {
            delete substitutionFilter;
            return 0;
        }
D
duke 已提交
289

P
prr 已提交
290 291 292 293 294
        // This is the cheapest way to get mark reordering only for Hebrew.
        // We could just do the mark reordering for all scripts, but most
        // of them probably don't need it...
        if (fScriptCode == hebrScriptCode) {
          reordered = LE_NEW_ARRAY(LEUnicode, count);
D
duke 已提交
295

P
prr 已提交
296 297 298 299 300
          if (reordered == NULL) {
            delete substitutionFilter;
            success = LE_MEMORY_ALLOCATION_ERROR;
            return 0;
          }
D
duke 已提交
301

P
prr 已提交
302 303
          CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, fakeGlyphStorage);
          inChars = reordered;
P
prr 已提交
304
        }
D
duke 已提交
305

S
srl 已提交
306
        fakeGlyphStorage.allocateAuxData(success);
D
duke 已提交
307 308

        if (LE_FAILURE(success)) {
S
srl 已提交
309
            delete substitutionFilter;
D
duke 已提交
310 311 312 313 314 315 316 317 318
            return 0;
        }

        if (rightToLeft) {
            out = count - 1;
            dir = -1;
        }

        for (i = 0; i < count; i += 1, out += dir) {
S
srl 已提交
319 320
            fakeGlyphStorage[out] = (LEGlyphID) inChars[i];
            fakeGlyphStorage.setAuxData(out, canonFeatures, success);
D
duke 已提交
321 322
        }

P
prr 已提交
323 324 325
        if (reordered != NULL) {
          LE_DELETE_ARRAY(reordered);
        }
D
duke 已提交
326

P
prr 已提交
327 328
        const LEReferenceTo<GlyphDefinitionTableHeader>  noGDEF; // empty gdef header
        outCharCount = canonGSUBTable->process(canonGSUBTable, fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, noGDEF, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
S
srl 已提交
329 330 331 332 333 334 335

        if (LE_FAILURE(success)) {
            delete substitutionFilter;
            return 0;
        }

        out = (rightToLeft? outCharCount - 1 : 0);
D
duke 已提交
336

S
srl 已提交
337 338 339 340 341 342 343
        /*
         * The char indices array in fakeGlyphStorage has the correct mapping
         * back to the original input characters. Save it in glyphStorage. The
         * subsequent call to glyphStoratge.allocateGlyphArray will keep this
         * array rather than allocating and initializing a new one.
         */
        glyphStorage.adoptCharIndicesArray(fakeGlyphStorage);
D
duke 已提交
344 345

        outChars = LE_NEW_ARRAY(LEUnicode, outCharCount);
S
srl 已提交
346 347 348 349 350 351 352

        if (outChars == NULL) {
            delete substitutionFilter;
            success = LE_MEMORY_ALLOCATION_ERROR;
            return 0;
        }

D
duke 已提交
353
        for (i = 0; i < outCharCount; i += 1, out += dir) {
S
srl 已提交
354
            outChars[out] = (LEUnicode) LE_GET_GLYPH(fakeGlyphStorage[i]);
D
duke 已提交
355 356 357 358 359 360 361 362
        }

        delete substitutionFilter;
    }

    return outCharCount;
}

363 364
le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
                                            LEGlyphStorage &glyphStorage, LEErrorCode &success)
D
duke 已提交
365 366 367 368 369
{
    if (LE_FAILURE(success)) {
        return 0;
    }

370
    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
D
duke 已提交
371 372 373 374 375
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    LEUnicode *outChars = NULL;
376
    le_int32 outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success);
D
duke 已提交
377 378

    if (outChars != NULL) {
379 380
        mapCharsToGlyphs(outChars, 0, outCharCount, rightToLeft, rightToLeft, glyphStorage, success);
        LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
D
duke 已提交
381
    } else {
382
        mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
D
duke 已提交
383 384 385 386 387 388 389
    }

    return glyphStorage.getGlyphCount();
}

// Input: glyphs
// Output: positions
390
void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y, LEErrorCode &success)
D
duke 已提交
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
{
    if (LE_FAILURE(success)) {
        return;
    }

    glyphStorage.allocatePositions(success);

    if (LE_FAILURE(success)) {
        return;
    }

    le_int32 i, glyphCount = glyphStorage.getGlyphCount();

    for (i = 0; i < glyphCount; i += 1) {
        LEPoint advance;

        glyphStorage.setPosition(i, x, y, success);
P
prr 已提交
408
        _LETRACE("g#%-4d (%.2f, %.2f)", i, x, y);
D
duke 已提交
409 410 411 412

        fFontInstance->getGlyphAdvance(glyphStorage[i], advance);
        x += advance.fX;
        y += advance.fY;
P
prr 已提交
413 414


D
duke 已提交
415 416 417 418 419
    }

    glyphStorage.setPosition(glyphCount, x, y, success);
}

420 421
void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
                                        LEGlyphStorage &glyphStorage, LEErrorCode &success)
D
duke 已提交
422 423 424 425 426 427 428 429 430 431
{
    if (LE_FAILURE(success)) {
        return;
    }

    if (chars == NULL || offset < 0 || count < 0) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

P
prr 已提交
432
    LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(LETableReference::kStaticData, (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable,
P
prr 已提交
433 434
                                                        CanonShaping::glyphDefinitionTableLen);
    CanonMarkFilter filter(gdefTable, success);
D
duke 已提交
435 436 437

    adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);

P
prr 已提交
438
    if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
P
prr 已提交
439 440 441
      LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
      KernTable kt(kernTable, success);
      kt.process(glyphStorage, success);
D
duke 已提交
442 443 444 445 446 447
    }

    // default is no adjustments
    return;
}

448
void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
D
duke 已提交
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
{
    float xAdjust = 0;
    le_int32 p, glyphCount = glyphStorage.getGlyphCount();

    if (LE_FAILURE(success)) {
        return;
    }

    if (markFilter == NULL) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    float ignore, prev;

    glyphStorage.getGlyphPosition(0, prev, ignore, success);

    for (p = 0; p < glyphCount; p += 1) {
        float next, xAdvance;

        glyphStorage.getGlyphPosition(p + 1, next, ignore, success);

        xAdvance = next - prev;
P
prr 已提交
472
        _LETRACE("p#%d (%.2f,%.2f)", p, xAdvance, 0);
D
duke 已提交
473 474
        glyphStorage.adjustPosition(p, xAdjust, 0, success);

P
prr 已提交
475
        if (markFilter->accept(glyphStorage[p], success)) {
D
duke 已提交
476 477 478 479 480 481 482 483 484
            xAdjust -= xAdvance;
        }

        prev = next;
    }

    glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
}

485
void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
D
duke 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
{
    float xAdjust = 0;
    le_int32 c = 0, direction = 1, p;
    le_int32 glyphCount = glyphStorage.getGlyphCount();

    if (LE_FAILURE(success)) {
        return;
    }

    if (markFilter == NULL) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    if (reverse) {
        c = glyphCount - 1;
        direction = -1;
    }

    float ignore, prev;

    glyphStorage.getGlyphPosition(0, prev, ignore, success);

    for (p = 0; p < charCount; p += 1, c += direction) {
        float next, xAdvance;

        glyphStorage.getGlyphPosition(p + 1, next, ignore, success);

        xAdvance = next - prev;
P
prr 已提交
515 516 517 518

        _LETRACE("p#%d (%.2f,%.2f)", p, xAdvance, 0);


D
duke 已提交
519 520
        glyphStorage.adjustPosition(p, xAdjust, 0, success);

P
prr 已提交
521
        if (markFilter->accept(chars[c], success)) {
D
duke 已提交
522 523 524 525 526 527 528 529 530
            xAdjust -= xAdvance;
        }

        prev = next;
    }

    glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
}

P
prr 已提交
531
const void *LayoutEngine::getFontTable(LETag tableTag, size_t &length) const
D
duke 已提交
532
{
P
prr 已提交
533
  return fFontInstance->getFontTable(tableTag, length);
D
duke 已提交
534 535
}

536 537
void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
                                    LEGlyphStorage &glyphStorage, LEErrorCode &success)
D
duke 已提交
538 539 540 541 542 543 544 545 546
{
    if (LE_FAILURE(success)) {
        return;
    }

    glyphStorage.allocateGlyphArray(count, reverse, success);

    DefaultCharMapper charMapper(TRUE, mirror);

S
srl 已提交
547
    fFontInstance->mapCharsToGlyphs(chars, offset, count, reverse, &charMapper, fFilterZeroWidth, glyphStorage);
D
duke 已提交
548 549 550 551 552
}

// Input: characters, font?
// Output: glyphs, positions, char indices
// Returns: number of glyphs
553 554
le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
                              float x, float y, LEErrorCode &success)
D
duke 已提交
555 556 557 558 559
{
    if (LE_FAILURE(success)) {
        return 0;
    }

560
    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
D
duke 已提交
561 562 563 564 565 566
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    le_int32 glyphCount;

S
srl 已提交
567 568 569 570
    if (fGlyphStorage->getGlyphCount() > 0) {
        fGlyphStorage->reset();
    }

571
    glyphCount = computeGlyphs(chars, offset, count, max, rightToLeft, *fGlyphStorage, success);
D
duke 已提交
572 573 574 575 576 577 578 579
    positionGlyphs(*fGlyphStorage, x, y, success);
    adjustGlyphPositions(chars, offset, count, rightToLeft, *fGlyphStorage, success);

    return glyphCount;
}

void LayoutEngine::reset()
{
P
prr 已提交
580
  if(fGlyphStorage!=NULL) {
D
duke 已提交
581
    fGlyphStorage->reset();
P
prr 已提交
582
  }
D
duke 已提交
583 584
}

585
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
D
duke 已提交
586
{
P
prr 已提交
587 588
  //kerning and ligatures - by default
  return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, LE_DEFAULT_FEATURE_FLAG, success);
D
duke 已提交
589 590
}

591
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
D
duke 已提交
592 593 594
{
    static const le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
    static const le_uint32 mortTableTag = LE_MORT_TABLE_TAG;
P
prr 已提交
595
    static const le_uint32 morxTableTag = LE_MORX_TABLE_TAG;
D
duke 已提交
596 597 598 599 600

    if (LE_FAILURE(success)) {
        return NULL;
    }

P
prr 已提交
601
    LEReferenceTo<GlyphSubstitutionTableHeader> gsubTable(fontInstance,gsubTableTag,success);
D
duke 已提交
602 603 604
    LayoutEngine *result = NULL;
    LETag scriptTag   = 0x00000000;
    LETag languageTag = 0x00000000;
P
prr 已提交
605
    LETag v2ScriptTag = OpenTypeLayoutEngine::getV2ScriptTag(scriptCode);
D
duke 已提交
606

S
srl 已提交
607 608 609
    // Right now, only invoke V2 processing for Devanagari.  TODO: Allow more V2 scripts as they are
    // properly tested.

P
prr 已提交
610 611 612 613
    if ( v2ScriptTag == dev2ScriptTag && gsubTable.isValid() && gsubTable->coversScript(gsubTable, v2ScriptTag, success )) {
      result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, TRUE, gsubTable, success);
    }
    else if (gsubTable.isValid() && gsubTable->coversScript(gsubTable, scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode), success)) {
D
duke 已提交
614 615 616 617 618 619 620 621 622 623 624
        switch (scriptCode) {
        case bengScriptCode:
        case devaScriptCode:
        case gujrScriptCode:
        case kndaScriptCode:
        case mlymScriptCode:
        case oryaScriptCode:
        case guruScriptCode:
        case tamlScriptCode:
        case teluScriptCode:
        case sinhScriptCode:
S
srl 已提交
625
            result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, FALSE, gsubTable, success);
D
duke 已提交
626 627 628
            break;

        case arabScriptCode:
S
srl 已提交
629 630 631
            result = new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
            break;

P
prr 已提交
632 633 634 635 636
        case hebrScriptCode:
            // Disable hebrew ligatures since they have only archaic uses, see ticket #8318
            result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags & ~kTypoFlagLiga, gsubTable, success);
            break;

S
srl 已提交
637 638
        case hangScriptCode:
            result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
D
duke 已提交
639 640 641 642 643 644 645 646 647 648
            break;

        case haniScriptCode:
            languageTag = OpenTypeLayoutEngine::getLangSysTag(languageCode);

            switch (languageCode) {
            case korLanguageCode:
            case janLanguageCode:
            case zhtLanguageCode:
            case zhsLanguageCode:
P
prr 已提交
649
              if (gsubTable->coversScriptAndLanguage(gsubTable, scriptTag, languageTag, success, TRUE)) {
S
srl 已提交
650
                    result = new HanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
D
duke 已提交
651
                    break;
P
prr 已提交
652
              }
D
duke 已提交
653 654 655

                // note: falling through to default case.
            default:
S
srl 已提交
656
                result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
D
duke 已提交
657 658 659 660
                break;
            }

            break;
S
srl 已提交
661

662
        case tibtScriptCode:
S
srl 已提交
663
            result = new TibetanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
664
            break;
D
duke 已提交
665 666

        case khmrScriptCode:
S
srl 已提交
667
            result = new KhmerOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
D
duke 已提交
668 669 670
            break;

        default:
S
srl 已提交
671
            result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
D
duke 已提交
672 673 674
            break;
        }
    } else {
P
prr 已提交
675 676 677 678
        LEReferenceTo<MorphTableHeader2> morxTable(fontInstance, morxTableTag, success);
        if (LE_SUCCESS(success) &&
            morxTable.isValid() &&
            SWAPL(morxTable->version)==0x00020000) {
P
prr 已提交
679
            result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success);
D
duke 已提交
680
        } else {
P
prr 已提交
681 682 683
          LEReferenceTo<MorphTableHeader> mortTable(fontInstance, mortTableTag, success);
          if (LE_SUCCESS(success) && mortTable.isValid() && SWAPL(mortTable->version)==0x00010000) { // mort
            result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success);
P
prr 已提交
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
            } else {
                switch (scriptCode) {
                    case bengScriptCode:
                    case devaScriptCode:
                    case gujrScriptCode:
                    case kndaScriptCode:
                    case mlymScriptCode:
                    case oryaScriptCode:
                    case guruScriptCode:
                    case tamlScriptCode:
                    case teluScriptCode:
                    case sinhScriptCode:
                    {
                        result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
                        break;
                    }
D
duke 已提交
700

P
prr 已提交
701 702 703
                case arabScriptCode:
                  result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
                  break;
D
duke 已提交
704

P
prr 已提交
705 706
                  //case hebrScriptCode:
                  //    return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
707

P
prr 已提交
708 709 710
                case thaiScriptCode:
                  result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
                  break;
S
srl 已提交
711

P
prr 已提交
712 713 714
                case hangScriptCode:
                  result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
                  break;
D
duke 已提交
715

P
prr 已提交
716 717 718 719
                    default:
                        result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
                        break;
                }
D
duke 已提交
720 721 722 723
            }
        }
    }

S
srl 已提交
724
    if (result && LE_FAILURE(success)) {
P
prr 已提交
725 726 727
      delete result;
      result = NULL;
    }
S
srl 已提交
728

D
duke 已提交
729 730 731 732 733 734 735 736 737 738
    if (result == NULL) {
        success = LE_MEMORY_ALLOCATION_ERROR;
    }

    return result;
}

LayoutEngine::~LayoutEngine() {
    delete fGlyphStorage;
}
739 740

U_NAMESPACE_END