X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b75a7d8f3b4adbae880cab104ce2c6a50eee4db2..e33e88b05ea89f292e476b668b5ee95a095e0ffb:/icuSources/layout/OpenTypeLayoutEngine.cpp diff --git a/icuSources/layout/OpenTypeLayoutEngine.cpp b/icuSources/layout/OpenTypeLayoutEngine.cpp index 730c79d6..9709e6ac 100644 --- a/icuSources/layout/OpenTypeLayoutEngine.cpp +++ b/icuSources/layout/OpenTypeLayoutEngine.cpp @@ -1,8 +1,7 @@ /* - * %W% %W% * - * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved + * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved * */ @@ -18,24 +17,42 @@ #include "GlyphDefinitionTables.h" #include "GlyphPositioningTables.h" +#include "LEGlyphStorage.h" + #include "GDEFMarkFilter.h" U_NAMESPACE_BEGIN -const char OpenTypeLayoutEngine::fgClassID=0; +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OpenTypeLayoutEngine) + +static const LETag emptyTag = 0x00000000; + +static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG; +static const LETag ligaFeatureTag = LE_LIGA_FEATURE_TAG; +static const LETag cligFeatureTag = LE_CLIG_FEATURE_TAG; +static const LETag kernFeatureTag = LE_KERN_FEATURE_TAG; +static const LETag markFeatureTag = LE_MARK_FEATURE_TAG; +static const LETag mkmkFeatureTag = LE_MKMK_FEATURE_TAG; + +static const LETag defaultFeatures[] = {ccmpFeatureTag, ligaFeatureTag, cligFeatureTag, kernFeatureTag, markFeatureTag, mkmkFeatureTag, emptyTag}; + OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const GlyphSubstitutionTableHeader *gsubTable) - : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fFeatureOrder(NULL), - fGSUBTable(gsubTable), fSubstitutionFilter(NULL) + : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureList(defaultFeatures), fFeatureOrder(NULL), + fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { - static le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; - static le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; - - fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); - fGPOSTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag); + static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; + static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; + const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag); setScriptAndLanguageTags(); + + fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); + + if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { + fGPOSTable = gposTable; + } } void OpenTypeLayoutEngine::reset() @@ -45,19 +62,10 @@ void OpenTypeLayoutEngine::reset() // will have been called already by // LayoutEngine::~LayoutEngine() LayoutEngine::reset(); - - // The double call could be avoided by - // puting the following into a private - // method that's called from here and - // from our destructor - if (fFeatureTags != NULL) { - LE_DELETE_ARRAY(fFeatureTags); - fFeatureTags = NULL; - } } OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode) - : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fFeatureOrder(NULL), + : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureOrder(NULL), fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { setScriptAndLanguageTags(); @@ -92,10 +100,38 @@ void OpenTypeLayoutEngine::setScriptAndLanguageTags() fLangSysTag = getLangSysTag(fLanguageCode); } +le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, + LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success) +{ + 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; + } + + le_int32 outCharCount = LayoutEngine::characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success); + + if (LE_FAILURE(success)) { + return 0; + } + + glyphStorage.allocateGlyphArray(outCharCount, rightToLeft, success); + glyphStorage.allocateAuxData(success); + + for (le_int32 i = 0; i < outCharCount; i += 1) { + glyphStorage.setAuxData(i, (void *) fFeatureList, success); + } + + return outCharCount; +} + // Input: characters, tags // Output: glyphs, char indices -le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, const LETag **featureTags, - LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success) +le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, + LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { return 0; @@ -106,24 +142,37 @@ le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 return 0; } - mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphs, charIndices, success); + mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success); if (LE_FAILURE(success)) { return 0; } if (fGSUBTable != NULL) { - fGSUBTable->process(glyphs, featureTags, count, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, fFeatureOrder); + count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, fFeatureOrder); } return count; } -le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success) +le_int32 OpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success) +{ + if (LE_FAILURE(success)) { + return 0; + } + + glyphStorage.adoptGlyphArray(tempGlyphStorage); + glyphStorage.adoptCharIndicesArray(tempGlyphStorage); + glyphStorage.adoptAuxDataArray(tempGlyphStorage); + glyphStorage.adoptGlyphCount(tempGlyphStorage); + + return glyphStorage.getGlyphCount(); +} + +le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphStorage &glyphStorage, LEErrorCode &success) { LEUnicode *outChars = NULL; - LEGlyphID *fakeGlyphs = NULL; - le_int32 *tempCharIndices = NULL; + LEGlyphStorage fakeGlyphStorage; le_int32 outCharCount, outGlyphCount, fakeGlyphCount; if (LE_FAILURE(success)) { @@ -135,48 +184,39 @@ le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 o return 0; } - outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, tempCharIndices, fFeatureTags, success); + outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, fakeGlyphStorage, success); if (outChars != NULL) { - fakeGlyphCount = glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fFeatureTags, fakeGlyphs, tempCharIndices, success); + fakeGlyphCount = glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fakeGlyphStorage, success); + LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work... //adjustGlyphs(outChars, 0, outCharCount, rightToLeft, fakeGlyphs, fakeGlyphCount); } else { - fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fFeatureTags, fakeGlyphs, tempCharIndices, success); + fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fakeGlyphStorage, success); //adjustGlyphs(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount); } - outGlyphCount = glyphPostProcessing(fakeGlyphs, tempCharIndices, fakeGlyphCount, glyphs, charIndices, success); - - if (outChars != chars) { - LE_DELETE_ARRAY(outChars); - } - - if (fakeGlyphs != glyphs) { - LE_DELETE_ARRAY(fakeGlyphs); - } - - if (tempCharIndices != charIndices) { - LE_DELETE_ARRAY(tempCharIndices); - } + outGlyphCount = glyphPostProcessing(fakeGlyphStorage, glyphStorage, success); return outGlyphCount; } // apply GPOS table, if any void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, - LEGlyphID glyphs[], le_int32 glyphCount, float positions[], LEErrorCode &success) + LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { return; } - if (chars == NULL || glyphs == NULL || positions == NULL || offset < 0 || count < 0) { + if (chars == NULL || offset < 0 || count < 0) { success = LE_ILLEGAL_ARGUMENT_ERROR; return; } + le_int32 glyphCount = glyphStorage.getGlyphCount(); + if (glyphCount > 0 && fGPOSTable != NULL) { - GlyphPositionAdjustment *adjustments = LE_NEW_ARRAY(GlyphPositionAdjustment, glyphCount); + GlyphPositionAdjustment *adjustments = new GlyphPositionAdjustment[glyphCount]; le_int32 i; if (adjustments == NULL) { @@ -184,6 +224,9 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 return; } +#if 0 + // Don't need to do this if we allocate + // the adjustments array w/ new... for (i = 0; i < glyphCount; i += 1) { adjustments[i].setXPlacement(0); adjustments[i].setYPlacement(0); @@ -193,8 +236,9 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 adjustments[i].setBaseOffset(-1); } +#endif - fGPOSTable->process(glyphs, adjustments, fFeatureTags, glyphCount, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance, fFeatureOrder); + fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance, fFeatureOrder); float xAdjust = 0, yAdjust = 0; @@ -217,21 +261,24 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 yPlacement += adjustments[base].getYPlacement(); } - positions[i*2] += xAdjust + fFontInstance->xUnitsToPoints(xPlacement); - positions[i*2+1] -= yAdjust + fFontInstance->yUnitsToPoints(yPlacement); + xPlacement = fFontInstance->xUnitsToPoints(xPlacement); + yPlacement = fFontInstance->yUnitsToPoints(yPlacement); + glyphStorage.adjustPosition(i, xAdjust + xPlacement, -(yAdjust + yPlacement), success); xAdjust += fFontInstance->xUnitsToPoints(xAdvance); yAdjust += fFontInstance->yUnitsToPoints(yAdvance); } - positions[glyphCount*2] += xAdjust; - positions[glyphCount*2+1] -= yAdjust; + glyphStorage.adjustPosition(glyphCount, xAdjust, -yAdjust, success); - LE_DELETE_ARRAY(adjustments); + delete[] adjustments; } +#if 0 + // Don't know why this is here... LE_DELETE_ARRAY(fFeatureTags); fFeatureTags = NULL; +#endif } U_NAMESPACE_END