1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/LayoutEngine.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,612 @@
1.4 +
1.5 +/*
1.6 + *
1.7 + * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
1.8 + *
1.9 + */
1.10 +
1.11 +#include "LETypes.h"
1.12 +#include "LEScripts.h"
1.13 +#include "LELanguages.h"
1.14 +
1.15 +#include "LayoutEngine.h"
1.16 +#include "ArabicLayoutEngine.h"
1.17 +#include "CanonShaping.h"
1.18 +#include "HanLayoutEngine.h"
1.19 +#include "IndicLayoutEngine.h"
1.20 +#include "KhmerLayoutEngine.h"
1.21 +#include "ThaiLayoutEngine.h"
1.22 +#include "GXLayoutEngine.h"
1.23 +#include "ScriptAndLanguageTags.h"
1.24 +#include "CharSubstitutionFilter.h"
1.25 +
1.26 +#include "LEGlyphStorage.h"
1.27 +
1.28 +#include "OpenTypeUtilities.h"
1.29 +#include "GlyphSubstitutionTables.h"
1.30 +#include "MorphTables.h"
1.31 +
1.32 +#include "DefaultCharMapper.h"
1.33 +
1.34 +#include "KernTable.h"
1.35 +
1.36 +U_NAMESPACE_BEGIN
1.37 +
1.38 +#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
1.39 +
1.40 +const LEUnicode32 DefaultCharMapper::controlChars[] = {
1.41 + 0x0009, 0x000A, 0x000D,
1.42 + /*0x200C, 0x200D,*/ 0x200E, 0x200F,
1.43 + 0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
1.44 + 0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
1.45 +};
1.46 +
1.47 +const le_int32 DefaultCharMapper::controlCharsCount = ARRAY_SIZE(controlChars);
1.48 +
1.49 +const LEUnicode32 DefaultCharMapper::mirroredChars[] = {
1.50 + 0x0028, 0x0029, // ascii paired punctuation
1.51 + 0x003c, 0x003e,
1.52 + 0x005b, 0x005d,
1.53 + 0x007b, 0x007d,
1.54 + 0x2045, 0x2046, // math symbols (not complete)
1.55 + 0x207d, 0x207e,
1.56 + 0x208d, 0x208e,
1.57 + 0x2264, 0x2265,
1.58 + 0x3008, 0x3009, // chinese paired punctuation
1.59 + 0x300a, 0x300b,
1.60 + 0x300c, 0x300d,
1.61 + 0x300e, 0x300f,
1.62 + 0x3010, 0x3011,
1.63 + 0x3014, 0x3015,
1.64 + 0x3016, 0x3017,
1.65 + 0x3018, 0x3019,
1.66 + 0x301a, 0x301b
1.67 +};
1.68 +
1.69 +const le_int32 DefaultCharMapper::mirroredCharsCount = ARRAY_SIZE(mirroredChars);
1.70 +
1.71 +LEUnicode32 DefaultCharMapper::mapChar(LEUnicode32 ch) const
1.72 +{
1.73 + if (fFilterControls) {
1.74 + le_int32 index = OpenTypeUtilities::search((le_uint32)ch, (le_uint32 *)controlChars, controlCharsCount);
1.75 +
1.76 + if (controlChars[index] == ch) {
1.77 + return 0xFFFF;
1.78 + }
1.79 + }
1.80 +
1.81 + if (fMirror) {
1.82 + le_int32 index = OpenTypeUtilities::search((le_uint32) ch, (le_uint32 *)mirroredChars, mirroredCharsCount);
1.83 +
1.84 + if (mirroredChars[index] == ch) {
1.85 + le_int32 mirrorOffset = ((index & 1) == 0) ? 1 : -1;
1.86 +
1.87 + return mirroredChars[index + mirrorOffset];
1.88 + }
1.89 + }
1.90 +
1.91 + return ch;
1.92 +}
1.93 +
1.94 +// This is here to get it out of LEGlyphFilter.h.
1.95 +// No particular reason to put it here, other than
1.96 +// this is a good central location...
1.97 +LEGlyphFilter::~LEGlyphFilter()
1.98 +{
1.99 + // nothing to do
1.100 +}
1.101 +
1.102 +CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
1.103 + : fFontInstance(fontInstance)
1.104 +{
1.105 + // nothing to do
1.106 +}
1.107 +
1.108 +CharSubstitutionFilter::~CharSubstitutionFilter()
1.109 +{
1.110 + // nothing to do
1.111 +}
1.112 +
1.113 +
1.114 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LayoutEngine)
1.115 +
1.116 +static const LETag emptyTag = 0x00000000;
1.117 +
1.118 +static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG;
1.119 +
1.120 +static const LETag canonFeatures[] = {ccmpFeatureTag, emptyTag};
1.121 +
1.122 +LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags)
1.123 + : fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode),
1.124 + fTypoFlags(typoFlags), fGidOfRA(0)
1.125 +{
1.126 + fGlyphStorage = new LEGlyphStorage();
1.127 +}
1.128 +
1.129 +le_bool LayoutEngine::isBogus()
1.130 +{
1.131 + return fGlyphStorage? FALSE : TRUE;
1.132 +}
1.133 +
1.134 +le_int32 LayoutEngine::getGlyphCount() const
1.135 +{
1.136 + return fGlyphStorage->getGlyphCount();
1.137 +}
1.138 +
1.139 +void LayoutEngine::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
1.140 +{
1.141 + fGlyphStorage->getCharIndices(charIndices, indexBase, success);
1.142 +}
1.143 +
1.144 +void LayoutEngine::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
1.145 +{
1.146 + fGlyphStorage->getCharIndices(charIndices, success);
1.147 +}
1.148 +
1.149 +// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
1.150 +void LayoutEngine::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
1.151 +{
1.152 + fGlyphStorage->getGlyphs(glyphs, extraBits, success);
1.153 +}
1.154 +
1.155 +void LayoutEngine::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
1.156 +{
1.157 + fGlyphStorage->getGlyphs(glyphs, success);
1.158 +}
1.159 +
1.160 +
1.161 +void LayoutEngine::getGlyphPositions(float positions[], LEErrorCode &success) const
1.162 +{
1.163 + fGlyphStorage->getGlyphPositions(positions, success);
1.164 +}
1.165 +
1.166 +void LayoutEngine::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
1.167 +{
1.168 + fGlyphStorage->getGlyphPosition(glyphIndex, x, y, success);
1.169 +}
1.170 +
1.171 +le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
1.172 + LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.173 +{
1.174 + if (LE_FAILURE(success)) {
1.175 + return 0;
1.176 + }
1.177 +
1.178 + if (offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
1.179 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.180 + return 0;
1.181 + }
1.182 +
1.183 + const GlyphSubstitutionTableHeader *canonGSUBTable = (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
1.184 + LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
1.185 + LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
1.186 + le_int32 i, dir = 1, out = 0, outCharCount = count;
1.187 +
1.188 + if (canonGSUBTable->coversScript(scriptTag)) {
1.189 + CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
1.190 + if (!substitutionFilter) {
1.191 + success = LE_MEMORY_ALLOCATION_ERROR;
1.192 + return 0;
1.193 + }
1.194 +
1.195 + const LEUnicode *inChars = &chars[offset];
1.196 + LEUnicode *reordered = NULL;
1.197 +
1.198 + // This is the cheapest way to get mark reordering only for Hebrew.
1.199 + // We could just do the mark reordering for all scripts, but most
1.200 + // of them probably don't need it...
1.201 + if (fScriptCode == hebrScriptCode) {
1.202 + reordered = LE_NEW_ARRAY(LEUnicode, count);
1.203 +
1.204 + if (reordered == NULL) {
1.205 + success = LE_MEMORY_ALLOCATION_ERROR;
1.206 + delete substitutionFilter;
1.207 + return 0;
1.208 + }
1.209 +
1.210 + CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, glyphStorage);
1.211 + inChars = reordered;
1.212 + }
1.213 +
1.214 + glyphStorage.allocateGlyphArray(count, rightToLeft, success);
1.215 + glyphStorage.allocateAuxData(success);
1.216 +
1.217 + if (LE_FAILURE(success)) {
1.218 + delete substitutionFilter;
1.219 + return 0;
1.220 + }
1.221 +
1.222 + if (rightToLeft) {
1.223 + out = count - 1;
1.224 + dir = -1;
1.225 + }
1.226 +
1.227 + for (i = 0; i < count; i += 1, out += dir) {
1.228 + glyphStorage[out] = (LEGlyphID) inChars[i];
1.229 + glyphStorage.setAuxData(out, (void *) canonFeatures, success);
1.230 + }
1.231 +
1.232 + if (reordered != NULL) {
1.233 + LE_DELETE_ARRAY(reordered);
1.234 + }
1.235 +
1.236 + outCharCount = canonGSUBTable->process(glyphStorage, rightToLeft,
1.237 + scriptTag, langSysTag, NULL, success, substitutionFilter, NULL);
1.238 +
1.239 + if (LE_FAILURE(success)) {
1.240 + delete substitutionFilter;
1.241 + return 0;
1.242 + }
1.243 +
1.244 + out = (rightToLeft? count - 1 : 0);
1.245 +
1.246 + outChars = LE_NEW_ARRAY(LEUnicode, outCharCount);
1.247 + if (!outChars) {
1.248 + delete substitutionFilter;
1.249 + success = LE_MEMORY_ALLOCATION_ERROR;
1.250 + return 0;
1.251 + }
1.252 + for (i = 0; i < outCharCount; i += 1, out += dir) {
1.253 + outChars[out] = (LEUnicode) LE_GET_GLYPH(glyphStorage[i]);
1.254 + }
1.255 +
1.256 + delete substitutionFilter;
1.257 + }
1.258 +
1.259 + return outCharCount;
1.260 +}
1.261 +
1.262 +le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
1.263 + LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.264 +{
1.265 + if (LE_FAILURE(success)) {
1.266 + return 0;
1.267 + }
1.268 +
1.269 + if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
1.270 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.271 + return 0;
1.272 + }
1.273 +
1.274 + LEUnicode *outChars = NULL;
1.275 + le_int32 outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success);
1.276 +
1.277 + if (outChars != NULL) {
1.278 + mapCharsToGlyphs(outChars, 0, outCharCount, rightToLeft, rightToLeft, glyphStorage, success);
1.279 + LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
1.280 + } else {
1.281 + mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
1.282 + }
1.283 +
1.284 + return glyphStorage.getGlyphCount();
1.285 +}
1.286 +
1.287 +// Input: glyphs
1.288 +// Output: positions
1.289 +void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y, LEErrorCode &success)
1.290 +{
1.291 + if (LE_FAILURE(success)) {
1.292 + return;
1.293 + }
1.294 +
1.295 + glyphStorage.allocatePositions(success);
1.296 +
1.297 + if (LE_FAILURE(success)) {
1.298 + return;
1.299 + }
1.300 +
1.301 + le_int32 i, glyphCount = glyphStorage.getGlyphCount();
1.302 +
1.303 + for (i = 0; i < glyphCount; i += 1) {
1.304 + LEPoint advance;
1.305 +
1.306 + glyphStorage.setPosition(i, x, y, success);
1.307 +
1.308 + fFontInstance->getGlyphAdvance(glyphStorage[i], advance);
1.309 + x += advance.fX;
1.310 + y += advance.fY;
1.311 + }
1.312 +
1.313 + glyphStorage.setPosition(glyphCount, x, y, success);
1.314 +}
1.315 +
1.316 +void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/,
1.317 + LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.318 +{
1.319 + if (LE_FAILURE(success)) {
1.320 + return;
1.321 + }
1.322 +
1.323 + if (chars == NULL || offset < 0 || count < 0) {
1.324 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.325 + return;
1.326 + }
1.327 +
1.328 + if (fTypoFlags & 0x1) { /* kerning enabled */
1.329 + static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
1.330 +
1.331 + KernTable kt(fFontInstance, getFontTable(kernTableTag));
1.332 + kt.process(glyphStorage);
1.333 + }
1.334 +
1.335 + // default is no adjustments
1.336 + return;
1.337 +}
1.338 +
1.339 +void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
1.340 +{
1.341 + float xAdjust = 0;
1.342 + le_int32 p, glyphCount = glyphStorage.getGlyphCount();
1.343 +
1.344 + if (LE_FAILURE(success)) {
1.345 + return;
1.346 + }
1.347 +
1.348 + if (markFilter == NULL) {
1.349 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.350 + return;
1.351 + }
1.352 +
1.353 + float ignore, prev;
1.354 +
1.355 + glyphStorage.getGlyphPosition(0, prev, ignore, success);
1.356 +
1.357 + for (p = 0; p < glyphCount; p += 1) {
1.358 + float next, xAdvance;
1.359 +
1.360 + glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
1.361 +
1.362 + xAdvance = next - prev;
1.363 + glyphStorage.adjustPosition(p, xAdjust, 0, success);
1.364 +
1.365 + if (markFilter->accept(glyphStorage[p])) {
1.366 + xAdjust -= xAdvance;
1.367 + }
1.368 +
1.369 + prev = next;
1.370 + }
1.371 +
1.372 + glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
1.373 +}
1.374 +
1.375 +void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
1.376 +{
1.377 + float xAdjust = 0;
1.378 + le_int32 c = 0, direction = 1, p;
1.379 + le_int32 glyphCount = glyphStorage.getGlyphCount();
1.380 +
1.381 + if (LE_FAILURE(success)) {
1.382 + return;
1.383 + }
1.384 +
1.385 + if (markFilter == NULL) {
1.386 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.387 + return;
1.388 + }
1.389 +
1.390 + if (reverse) {
1.391 + c = glyphCount - 1;
1.392 + direction = -1;
1.393 + }
1.394 +
1.395 + float ignore, prev;
1.396 +
1.397 + glyphStorage.getGlyphPosition(0, prev, ignore, success);
1.398 +
1.399 + for (p = 0; p < charCount; p += 1, c += direction) {
1.400 + float next, xAdvance;
1.401 +
1.402 + glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
1.403 +
1.404 + xAdvance = next - prev;
1.405 + glyphStorage.adjustPosition(p, xAdjust, 0, success);
1.406 +
1.407 + if (markFilter->accept(chars[c])) {
1.408 + xAdjust -= xAdvance;
1.409 + }
1.410 +
1.411 + prev = next;
1.412 + }
1.413 +
1.414 + glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
1.415 +}
1.416 +
1.417 +const void *LayoutEngine::getFontTable(LETag tableTag) const
1.418 +{
1.419 + return fFontInstance->getFontTable(tableTag);
1.420 +}
1.421 +
1.422 +void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
1.423 + LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.424 +{
1.425 + if (LE_FAILURE(success)) {
1.426 + return;
1.427 + }
1.428 +
1.429 + glyphStorage.allocateGlyphArray(count, reverse, success);
1.430 +
1.431 + DefaultCharMapper charMapper(TRUE, mirror);
1.432 +
1.433 + fFontInstance->mapCharsToGlyphs(chars, offset, count, reverse, &charMapper, glyphStorage);
1.434 +}
1.435 +
1.436 +// Input: characters, font?
1.437 +// Output: glyphs, positions, char indices
1.438 +// Returns: number of glyphs
1.439 +le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
1.440 + float x, float y, LEErrorCode &success)
1.441 +{
1.442 + if (LE_FAILURE(success)) {
1.443 + return 0;
1.444 + }
1.445 +
1.446 + if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
1.447 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.448 + return 0;
1.449 + }
1.450 +
1.451 + // 1922 mlyl: get the glyph ID of RAKAR -->
1.452 + const LEUnicode RAKAR[] = {0xFFFF, 0xD15, 0xD4D, 0xD30, 0xFFFF};
1.453 + if (fGidOfRA == 0 && mlymScriptCode == fScriptCode) {
1.454 + fGidOfRA = -1; // 0xFFFFFFFF
1.455 + TInt noOfGlyphs = layoutChars(
1.456 + RAKAR, // chars - the input character context
1.457 + 1, // the offset of the first character to process
1.458 + 3, // count - the number of characters to process // offset
1.459 + 5, // max - the number of characters in the input context // size of text
1.460 + FALSE, // rightToLeft - TRUE if the characters are in a right to left directional run
1.461 + 0, // start X
1.462 + 0, // start Y
1.463 + success); // result code
1.464 +
1.465 + if (!LE_FAILURE(success)) {
1.466 + fGidOfRA = (*fGlyphStorage)[1];
1.467 + (*fGlyphStorage).reset();
1.468 + }
1.469 + }
1.470 + // <-- 1922 mlyl
1.471 +
1.472 + le_int32 glyphCount;
1.473 +
1.474 + glyphCount = computeGlyphs(chars, offset, count, max, rightToLeft, *fGlyphStorage, success);
1.475 +
1.476 + // 1922 mlyl: put RAKAR left of the preceding glyph -->
1.477 + if (fGidOfRA != 0 && fGidOfRA != -1 && mlymScriptCode == fScriptCode) {
1.478 + fGlyphStorage->forMlylRakar(fGidOfRA);
1.479 + }
1.480 + // <-- 1922 mlyl
1.481 +
1.482 + positionGlyphs(*fGlyphStorage, x, y, success);
1.483 + adjustGlyphPositions(chars, offset, count, rightToLeft, *fGlyphStorage, success);
1.484 +
1.485 + return glyphCount;
1.486 +}
1.487 +
1.488 +void LayoutEngine::reset()
1.489 +{
1.490 + fGlyphStorage->reset();
1.491 +}
1.492 +
1.493 +LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
1.494 +{
1.495 + // 3 -> kerning and ligatures
1.496 + return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, 3, success);
1.497 +}
1.498 +
1.499 +LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
1.500 +{
1.501 + static const le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
1.502 + static const le_uint32 mortTableTag = LE_MORT_TABLE_TAG;
1.503 +
1.504 + if (LE_FAILURE(success)) {
1.505 + return NULL;
1.506 + }
1.507 +
1.508 + const GlyphSubstitutionTableHeader *gsubTable = (const GlyphSubstitutionTableHeader *) fontInstance->getFontTable(gsubTableTag);
1.509 + LayoutEngine *result = NULL;
1.510 + LETag scriptTag = 0x00000000;
1.511 + LETag languageTag = 0x00000000;
1.512 +
1.513 + if (gsubTable != NULL && gsubTable->coversScript(scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode))) {
1.514 + switch (scriptCode) {
1.515 + case bengScriptCode:
1.516 + case devaScriptCode:
1.517 + case gujrScriptCode:
1.518 + case kndaScriptCode:
1.519 + case mlymScriptCode:
1.520 + case oryaScriptCode:
1.521 + case guruScriptCode:
1.522 + case tamlScriptCode:
1.523 + case teluScriptCode:
1.524 + result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
1.525 + break;
1.526 +
1.527 + case arabScriptCode:
1.528 + result = new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
1.529 + break;
1.530 +
1.531 + case haniScriptCode:
1.532 + languageTag = OpenTypeLayoutEngine::getLangSysTag(languageCode);
1.533 +
1.534 + switch (languageCode) {
1.535 + case korLanguageCode:
1.536 + case janLanguageCode:
1.537 + case zhtLanguageCode:
1.538 + case zhsLanguageCode:
1.539 + if (gsubTable->coversScriptAndLanguage(scriptTag, languageTag, TRUE)) {
1.540 + result = new HanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
1.541 + break;
1.542 + }
1.543 +
1.544 + // note: falling through to default case.
1.545 + default:
1.546 + result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
1.547 + break;
1.548 + }
1.549 +
1.550 + break;
1.551 +
1.552 + case khmrScriptCode:
1.553 + result = new KhmerOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
1.554 + break;
1.555 +
1.556 + default:
1.557 + result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
1.558 + break;
1.559 + }
1.560 + } else {
1.561 + const MorphTableHeader *morphTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
1.562 +
1.563 + if (morphTable != NULL) {
1.564 + result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, morphTable);
1.565 + } else {
1.566 + switch (scriptCode) {
1.567 + case bengScriptCode:
1.568 + case devaScriptCode:
1.569 + case gujrScriptCode:
1.570 + case kndaScriptCode:
1.571 + case mlymScriptCode:
1.572 + case oryaScriptCode:
1.573 + case guruScriptCode:
1.574 + case tamlScriptCode:
1.575 + case teluScriptCode:
1.576 + {
1.577 + result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
1.578 + break;
1.579 + }
1.580 +
1.581 + case arabScriptCode:
1.582 + //case hebrScriptCode:
1.583 + result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
1.584 + break;
1.585 +
1.586 + //case hebrScriptCode:
1.587 + // return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
1.588 +
1.589 + case thaiScriptCode:
1.590 + result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
1.591 + break;
1.592 +
1.593 + default:
1.594 + result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
1.595 + break;
1.596 + }
1.597 + }
1.598 + }
1.599 +
1.600 + if (result && result->isBogus()) {
1.601 + delete result;
1.602 + result = NULL;
1.603 + }
1.604 + if (result == NULL) {
1.605 + success = LE_MEMORY_ALLOCATION_ERROR;
1.606 + }
1.607 +
1.608 + return result;
1.609 +}
1.610 +
1.611 +LayoutEngine::~LayoutEngine() {
1.612 + delete fGlyphStorage;
1.613 +}
1.614 +
1.615 +U_NAMESPACE_END