/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2006 - All Rights Reserved
*
*/
#include "LayoutEngine.h"
#include "OpenTypeLayoutEngine.h"
#include "ScriptAndLanguageTags.h"
+#include "CharSubstitutionFilter.h"
#include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
#include "GlyphPositioningTables.h"
#include "LEGlyphStorage.h"
+#include "GlyphPositionAdjustments.h"
#include "GDEFMarkFilter.h"
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};
+#define ccmpFeatureTag LE_CCMP_FEATURE_TAG
+#define ligaFeatureTag LE_LIGA_FEATURE_TAG
+#define cligFeatureTag LE_CLIG_FEATURE_TAG
+#define kernFeatureTag LE_KERN_FEATURE_TAG
+#define markFeatureTag LE_MARK_FEATURE_TAG
+#define mkmkFeatureTag LE_MKMK_FEATURE_TAG
+
+// 'dlig' not used at the moment
+#define dligFeatureTag 0x646C6967
+
+// 'palt'
+#define paltFeatureTag 0x70616C74
+
+#define ccmpFeatureMask 0x80000000UL
+#define ligaFeatureMask 0x40000000UL
+#define cligFeatureMask 0x20000000UL
+#define kernFeatureMask 0x10000000UL
+#define paltFeatureMask 0x08000000UL
+#define markFeatureMask 0x04000000UL
+#define mkmkFeatureMask 0x02000000UL
+
+#define minimalFeatures (ccmpFeatureMask | markFeatureMask | mkmkFeatureMask)
+#define ligaFeatures (ligaFeatureMask | cligFeatureMask | minimalFeatures)
+#define kernFeatures (kernFeatureMask | paltFeatureMask | minimalFeatures)
+#define kernAndLigaFeatures (ligaFeatures | kernFeatures)
+
+static const FeatureMap featureMap[] =
+{
+ {ccmpFeatureTag, ccmpFeatureMask},
+ {ligaFeatureTag, ligaFeatureMask},
+ {cligFeatureTag, cligFeatureMask},
+ {kernFeatureTag, kernFeatureMask},
+ {paltFeatureTag, paltFeatureMask},
+ {markFeatureTag, markFeatureMask},
+ {mkmkFeatureTag, mkmkFeatureMask}
+};
+static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap);
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- const GlyphSubstitutionTableHeader *gsubTable)
- : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureList(defaultFeatures), fFeatureOrder(NULL),
- fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
+ le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable)
+ : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags), fFeatureMask(minimalFeatures),
+ fFeatureMap(featureMap), fFeatureMapCount(featureMapCount), fFeatureOrder(FALSE),
+ fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL), fFilterZeroWidth(TRUE)
{
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);
+ // todo: switch to more flags and bitfield rather than list of feature tags?
+ switch (typoFlags & ~0x80000000L) {
+ case 0: break; // default
+ case 1: fFeatureMask = kernFeatures; break;
+ case 2: fFeatureMask = ligaFeatures; break;
+ case 3: fFeatureMask = kernAndLigaFeatures; break;
+ default: break;
+ }
+
+ if (typoFlags & 0x80000000L) {
+ fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
+ }
+
setScriptAndLanguageTags();
fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag);
LayoutEngine::reset();
}
-OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
- : LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureOrder(NULL),
- fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
+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)
{
setScriptAndLanguageTags();
}
OpenTypeLayoutEngine::~OpenTypeLayoutEngine()
{
+ if (fTypoFlags & 0x80000000L) {
+ delete fSubstitutionFilter;
+ }
+
reset();
}
glyphStorage.allocateAuxData(success);
for (le_int32 i = 0; i < outCharCount; i += 1) {
- glyphStorage.setAuxData(i, (void *) fFeatureList, success);
+ glyphStorage.setAuxData(i, fFeatureMask, success);
}
return outCharCount;
return 0;
}
- mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
+ mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, fFilterZeroWidth, glyphStorage, success);
if (LE_FAILURE(success)) {
return 0;
}
if (fGSUBTable != NULL) {
- count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, fFeatureOrder);
+ count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
+ fFeatureMap, fFeatureMapCount, fFeatureOrder);
}
return count;
outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, fakeGlyphStorage, success);
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
if (outChars != NULL) {
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(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount);
}
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
outGlyphCount = glyphPostProcessing(fakeGlyphStorage, glyphStorage, success);
return outGlyphCount;
le_int32 glyphCount = glyphStorage.getGlyphCount();
if (glyphCount > 0 && fGPOSTable != NULL) {
- GlyphPositionAdjustment *adjustments = new GlyphPositionAdjustment[glyphCount];
+ GlyphPositionAdjustments *adjustments = new GlyphPositionAdjustments(glyphCount);
le_int32 i;
if (adjustments == NULL) {
// 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);
+ adjustments->setXPlacement(i, 0);
+ adjustments->setYPlacement(i, 0);
- adjustments[i].setXAdvance(0);
- adjustments[i].setYAdvance(0);
+ adjustments->setXAdvance(i, 0);
+ adjustments->setYAdvance(i, 0);
- adjustments[i].setBaseOffset(-1);
+ adjustments->setBaseOffset(i, -1);
}
#endif
- fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance, fFeatureOrder);
+ fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance,
+ fFeatureMap, fFeatureMapCount, fFeatureOrder);
float xAdjust = 0, yAdjust = 0;
for (i = 0; i < glyphCount; i += 1) {
- float xAdvance = adjustments[i].getXAdvance();
- float yAdvance = adjustments[i].getYAdvance();
+ float xAdvance = adjustments->getXAdvance(i);
+ float yAdvance = adjustments->getYAdvance(i);
float xPlacement = 0;
float yPlacement = 0;
yAdjust += yKerning;
#endif
- for (le_int32 base = i; base >= 0; base = adjustments[base].getBaseOffset()) {
- xPlacement += adjustments[base].getXPlacement();
- yPlacement += adjustments[base].getYPlacement();
+ for (le_int32 base = i; base >= 0; base = adjustments->getBaseOffset(base)) {
+ xPlacement += adjustments->getXPlacement(base);
+ yPlacement += adjustments->getYPlacement(base);
}
xPlacement = fFontInstance->xUnitsToPoints(xPlacement);
glyphStorage.adjustPosition(glyphCount, xAdjust, -yAdjust, success);
- delete[] adjustments;
+ delete adjustments;
}
#if 0