X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..b25be06635768807f8f693286fa73bb2297bb06c:/icuSources/layout/OpenTypeLayoutEngine.cpp diff --git a/icuSources/layout/OpenTypeLayoutEngine.cpp b/icuSources/layout/OpenTypeLayoutEngine.cpp index fbbfc0e6..13479b44 100644 --- a/icuSources/layout/OpenTypeLayoutEngine.cpp +++ b/icuSources/layout/OpenTypeLayoutEngine.cpp @@ -1,7 +1,7 @@ /* * - * (C) Copyright IBM Corp. 1998-2006 - All Rights Reserved + * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved * */ @@ -10,6 +10,7 @@ #include "LELanguages.h" #include "LayoutEngine.h" +#include "CanonShaping.h" #include "OpenTypeLayoutEngine.h" #include "ScriptAndLanguageTags.h" #include "CharSubstitutionFilter.h" @@ -23,6 +24,8 @@ #include "GDEFMarkFilter.h" +#include "KernTable.h" + U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OpenTypeLayoutEngine) @@ -33,6 +36,8 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OpenTypeLayoutEngine) #define kernFeatureTag LE_KERN_FEATURE_TAG #define markFeatureTag LE_MARK_FEATURE_TAG #define mkmkFeatureTag LE_MKMK_FEATURE_TAG +#define loclFeatureTag LE_LOCL_FEATURE_TAG +#define caltFeatureTag LE_CALT_FEATURE_TAG // 'dlig' not used at the moment #define dligFeatureTag 0x646C6967 @@ -47,8 +52,10 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OpenTypeLayoutEngine) #define paltFeatureMask 0x08000000UL #define markFeatureMask 0x04000000UL #define mkmkFeatureMask 0x02000000UL +#define loclFeatureMask 0x01000000UL +#define caltFeatureMask 0x00800000UL -#define minimalFeatures (ccmpFeatureMask | markFeatureMask | mkmkFeatureMask) +#define minimalFeatures (ccmpFeatureMask | markFeatureMask | mkmkFeatureMask | loclFeatureMask | caltFeatureMask) #define ligaFeatures (ligaFeatureMask | cligFeatureMask | minimalFeatures) #define kernFeatures (kernFeatureMask | paltFeatureMask | minimalFeatures) #define kernAndLigaFeatures (ligaFeatures | kernFeatures) @@ -58,19 +65,21 @@ static const FeatureMap featureMap[] = {ccmpFeatureTag, ccmpFeatureMask}, {ligaFeatureTag, ligaFeatureMask}, {cligFeatureTag, cligFeatureMask}, - {kernFeatureTag, kernFeatureMask}, + {kernFeatureTag, kernFeatureMask}, {paltFeatureTag, paltFeatureMask}, {markFeatureTag, markFeatureMask}, - {mkmkFeatureTag, mkmkFeatureMask} + {mkmkFeatureTag, mkmkFeatureMask}, + {loclFeatureTag, loclFeatureMask}, + {caltFeatureTag, caltFeatureMask} }; static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap); OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, - le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable) - : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags), fFeatureMask(minimalFeatures), + le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success) + : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureMask(minimalFeatures), fFeatureMap(featureMap), fFeatureMapCount(featureMapCount), fFeatureOrder(FALSE), - fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL), fFilterZeroWidth(TRUE) + fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; @@ -93,7 +102,9 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); - if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { +// JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font +// if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { + if (gposTable != NULL && gposTable->coversScript(fScriptTag)) { fGPOSTable = gposTable; } } @@ -108,9 +119,9 @@ void OpenTypeLayoutEngine::reset() } OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, - le_int32 typoFlags) - : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags), fFeatureOrder(FALSE), - fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL), fFilterZeroWidth(TRUE) + le_int32 typoFlags, LEErrorCode &success) + : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureOrder(FALSE), + fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { setScriptAndLanguageTags(); } @@ -129,10 +140,25 @@ LETag OpenTypeLayoutEngine::getScriptTag(le_int32 scriptCode) if (scriptCode < 0 || scriptCode >= scriptCodeCount) { return 0xFFFFFFFF; } - return scriptTags[scriptCode]; } +LETag OpenTypeLayoutEngine::getV2ScriptTag(le_int32 scriptCode) +{ + switch (scriptCode) { + case bengScriptCode : return bng2ScriptTag; + case devaScriptCode : return dev2ScriptTag; + case gujrScriptCode : return gjr2ScriptTag; + case guruScriptCode : return gur2ScriptTag; + case kndaScriptCode : return knd2ScriptTag; + case mlymScriptCode : return mlm2ScriptTag; + case oryaScriptCode : return ory2ScriptTag; + case tamlScriptCode : return tml2ScriptTag; + case teluScriptCode : return tel2ScriptTag; + default: return nullScriptTag; + } +} + LETag OpenTypeLayoutEngine::getLangSysTag(le_int32 languageCode) { if (languageCode < 0 || languageCode >= languageCodeCount) { @@ -145,6 +171,7 @@ LETag OpenTypeLayoutEngine::getLangSysTag(le_int32 languageCode) void OpenTypeLayoutEngine::setScriptAndLanguageTags() { fScriptTag = getScriptTag(fScriptCode); + fScriptTagV2 = getV2ScriptTag(fScriptCode); fLangSysTag = getLangSysTag(fLanguageCode); } @@ -160,20 +187,39 @@ le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_i return 0; } - le_int32 outCharCount = LayoutEngine::characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success); + // 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... Another option would be to + // add a HebrewOpenTypeLayoutEngine subclass, but the only thing it + // would need to do is mark reordering, so that seems like overkill. + if (fScriptCode == hebrScriptCode) { + outChars = LE_NEW_ARRAY(LEUnicode, count); + + if (outChars == NULL) { + success = LE_MEMORY_ALLOCATION_ERROR; + return 0; + } + + if (LE_FAILURE(success)) { + LE_DELETE_ARRAY(outChars); + return 0; + } + + CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage); + } if (LE_FAILURE(success)) { return 0; } - glyphStorage.allocateGlyphArray(outCharCount, rightToLeft, success); + glyphStorage.allocateGlyphArray(count, rightToLeft, success); glyphStorage.allocateAuxData(success); - for (le_int32 i = 0; i < outCharCount; i += 1) { + for (le_int32 i = 0; i < count; i += 1) { glyphStorage.setAuxData(i, fFeatureMask, success); } - return outCharCount; + return count; } // Input: characters, tags @@ -190,20 +236,52 @@ le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 return 0; } - mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, fFilterZeroWidth, glyphStorage, success); + mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success); if (LE_FAILURE(success)) { return 0; } - + if (fGSUBTable != NULL) { + if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) { + count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter, + fFeatureMap, fFeatureMapCount, fFeatureOrder, success); + + } else { count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, - fFeatureMap, fFeatureMapCount, fFeatureOrder); + fFeatureMap, fFeatureMapCount, fFeatureOrder, success); + } } return count; } +// Input: characters, tags +// Output: glyphs, char indices +le_int32 OpenTypeLayoutEngine::glyphSubstitution(le_int32 count, le_int32 max, le_bool rightToLeft, + LEGlyphStorage &glyphStorage, LEErrorCode &success) +{ + if (LE_FAILURE(success)) { + return 0; + } + if ( count < 0 || max < 0 ) { + success = LE_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + if (fGSUBTable != NULL) { + if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) { + count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter, + fFeatureMap, fFeatureMapCount, fFeatureOrder, success); + + } else { + count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, + fFeatureMap, fFeatureMapCount, fFeatureOrder, success); + } + } + + return count; +} le_int32 OpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { @@ -271,8 +349,11 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 } le_int32 glyphCount = glyphStorage.getGlyphCount(); + if (glyphCount == 0) { + return; + } - if (glyphCount > 0 && fGPOSTable != NULL) { + if (fGPOSTable != NULL) { GlyphPositionAdjustments *adjustments = new GlyphPositionAdjustments(glyphCount); le_int32 i; @@ -295,8 +376,20 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 } #endif - fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance, - fFeatureMap, fFeatureMapCount, fFeatureOrder); + if (fGPOSTable != NULL) { + if (fScriptTagV2 != nullScriptTag && fGPOSTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) { + fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag, fGDEFTable, success, fFontInstance, + fFeatureMap, fFeatureMapCount, fFeatureOrder); + + } else { + fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, success, fFontInstance, + fFeatureMap, fFeatureMapCount, fFeatureOrder); + } + } else if ( fTypoFlags & 0x1 ) { + static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG; + KernTable kt(fFontInstance, getFontTable(kernTableTag)); + kt.process(glyphStorage); + } float xAdjust = 0, yAdjust = 0; @@ -330,6 +423,21 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 glyphStorage.adjustPosition(glyphCount, xAdjust, -yAdjust, success); delete adjustments; + } else { + // if there was no GPOS table, maybe there's non-OpenType kerning we can use + LayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success); + } + + LEGlyphID zwnj = fFontInstance->mapCharToGlyph(0x200C); + + if (zwnj != 0x0000) { + for (le_int32 g = 0; g < glyphCount; g += 1) { + LEGlyphID glyph = glyphStorage[g]; + + if (glyph == zwnj) { + glyphStorage[g] = LE_SET_GLYPH(glyph, 0xFFFF); + } + } } #if 0