summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp')
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp211
1 files changed, 132 insertions, 79 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
index d8ef3ed3a04..80a787b3469 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
+++ b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
@@ -54,6 +54,12 @@ static le_int32 getLanguageCode(LETag languageTag)
return -1;
}
+/*
+ * XeTeXOTLayoutEngine
+ */
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(XeTeXOTLayoutEngine)
+
LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
(const XeTeXFontInst* fontInstance,
LETag scriptTag, LETag languageTag,
@@ -62,11 +68,13 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
LEErrorCode &success)
{
static le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
+ static le_uint32 gposTableTag = LE_GPOS_TABLE_TAG;
if (LE_FAILURE(success))
return NULL;
const GlyphSubstitutionTableHeader* gsubTable = (const GlyphSubstitutionTableHeader*)fontInstance->getFontTable(gsubTableTag);
+ const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)fontInstance->getFontTable(gposTableTag);
LayoutEngine *result = NULL;
le_uint32 scriptCode = getScriptCode(scriptTag);
@@ -74,7 +82,8 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
le_int32 typoFlags = 3;
- if (gsubTable != NULL && gsubTable->coversScript(scriptTag)) {
+ if ((gsubTable != NULL && gsubTable->coversScript(scriptTag))
+ || (gposTable != NULL && gposTable->coversScript(scriptTag))) {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
@@ -102,7 +111,7 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
case hiraScriptCode:
case kanaScriptCode:
case hrktScriptCode:
- result = new XeTeXHanLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, addParams, removeFeatures);
+ result = new XeTeXHanLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, gposTable, addFeatures, addParams, removeFeatures);
break;
case khmrScriptCode:
@@ -110,7 +119,7 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
break;
default:
- result = new XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, addParams, removeFeatures);
+ result = new XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, gposTable, addFeatures, addParams, removeFeatures);
break;
}
}
@@ -149,21 +158,13 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
return result;
}
-/*
- * XeTeXOTLayoutEngine
- */
-
-const char XeTeXOTLayoutEngine::fgClassID=0;
-
XeTeXOTLayoutEngine::XeTeXOTLayoutEngine(
const LEFontInstance* fontInstance, LETag scriptTag, LETag languageTag,
- const GlyphSubstitutionTableHeader* gsubTable,
+ const GlyphSubstitutionTableHeader* gsubTable, const GlyphPositioningTableHeader* gposTable,
const LETag* addFeatures, const le_int32* addParams, const LETag* removeFeatures)
: OpenTypeLayoutEngine(fontInstance, getScriptCode(scriptTag), getLanguageCode(languageTag), 3, gsubTable)
{
- static le_uint32 gposTableTag = LE_GPOS_TABLE_TAG;
-
- fDefaultFeatures = fFeatureList;
+ fDefaultFeatureMap = fFeatureMap;
// check the result of setScriptAndLanguageTags(), in case they were unknown to ICU
if (fScriptTag != scriptTag || fLangSysTag != languageTag) {
@@ -172,7 +173,6 @@ XeTeXOTLayoutEngine::XeTeXOTLayoutEngine(
// reset the GPOS if the tags changed
fGPOSTable = NULL;
- const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag);
if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) {
fGPOSTable = gposTable;
}
@@ -183,8 +183,8 @@ XeTeXOTLayoutEngine::XeTeXOTLayoutEngine(
XeTeXOTLayoutEngine::~XeTeXOTLayoutEngine()
{
- if (fFeatureList != NULL && fFeatureList != fDefaultFeatures)
- LE_DELETE_ARRAY(fFeatureList);
+ if (fFeatureMap != NULL && fFeatureMap != fDefaultFeatureMap)
+ LE_DELETE_ARRAY(fFeatureMap);
if (fFeatureParamList != NULL)
LE_DELETE_ARRAY(fFeatureParamList);
}
@@ -194,69 +194,104 @@ void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const le_int32* a
// bail out if nothing was requested!
if ((addTags == NULL || *addTags == emptyTag) && (removeTags == NULL || *removeTags == emptyTag))
return;
-
- // count the max possible number of tags we might end up with
- le_uint32 count = 0;
- const LETag* pTag = fFeatureList;
- while (*pTag++ != emptyTag)
- count++;
- if (addTags != NULL && *addTags != emptyTag) {
- pTag = addTags;
- while (*pTag++ != emptyTag)
- count++;
+
+ // figure out total tag count: initial set - removed tags + added tags omitting duplicates
+ le_int32 totalCount = 0;
+ for (le_int32 i = 0; i < fFeatureMapCount; ++i) {
+ // skip any that are disabled by the mask
+ if ((fFeatureMask & fFeatureMap[i].mask) != 0) {
+ bool remove = false;
+ for (const LETag* r = removeTags; r != NULL && *r != emptyTag; ++r)
+ if (*r == fFeatureMap[i].tag) {
+ remove = true;
+ break;
+ }
+ if (!remove)
+ ++totalCount;
+ }
}
-
- // allocate new array for the tag list, big enough for max count
- LETag* newList = LE_NEW_ARRAY(LETag, count + 1);
-
- // copy the existing tags, skipping any in the remove list
- LETag* dest = newList;
- le_int32* newParams = LE_NEW_ARRAY(le_int32, count);
- le_int32* dest2 = newParams;
- pTag = fFeatureList;
- while (*pTag != emptyTag) {
- const LETag* t = removeTags;
- if (t != NULL)
- while (*t != emptyTag)
- if (*t == *pTag)
+ for (const LETag* a = addTags; a != NULL && *a != emptyTag; ++a) {
+ // before counting an add tag, check original map, and check for duplicates in list
+ bool add = true;
+ for (le_int32 i = 0; i < fFeatureMapCount; ++i)
+ if (*a == fFeatureMap[i].tag) {
+ if ((fFeatureMask & fFeatureMap[i].mask) != 0)
+ add = false;
+ break;
+ }
+ if (add) {
+ for (const LETag* t = addTags; t != a; ++t)
+ if (*a == *t) {
+ add = false;
break;
- else
- t++;
- if (t == NULL || *t == emptyTag) {
- *dest++ = *pTag;
- *dest2++ = 0;
+ }
}
- pTag++;
+ if (add)
+ ++totalCount;
}
- // copy the added tags and parameters, skipping any already present
- pTag = addTags;
- const le_int32* pParam = addParams;
- if (pTag != NULL)
- while (*pTag != emptyTag) {
- const LETag* t = newList;
- while (t < dest)
- if (*t == *pTag)
+ if (totalCount > 32)
+ fprintf(stderr, "\n*** feature count exceeds mask size; some features will be ignored\n");
+
+ // allocate new map
+ FeatureMap* newFeatureMap = LE_NEW_ARRAY(FeatureMap, totalCount);
+ le_int32 newFeatureCount = 0;
+ le_int32* newParamList = (addParams == NULL) ? NULL : LE_NEW_ARRAY(le_int32, totalCount);
+
+ // copy the features into the map and assign mask bits
+ FeatureMask newFeatureMask = 0;
+ FeatureMask maskBit = 0x80000000UL;
+ for (le_int32 i = 0; i < fFeatureMapCount; ++i) {
+ bool remove = false;
+ if ((fFeatureMask & fFeatureMap[i].mask) == 0)
+ remove = true;
+ else
+ for (const LETag* r = removeTags; r != NULL && *r != emptyTag; ++r)
+ if (*r == fFeatureMap[i].tag) {
+ remove = true;
break;
- else
- t++;
- if (t == dest) {
- *dest++ = *pTag;
- *dest2++ = *pParam;
+ }
+ if (!remove) {
+ newFeatureMap[newFeatureCount].tag = fFeatureMap[i].tag;
+ newFeatureMap[newFeatureCount].mask = maskBit;
+ if (newParamList != NULL)
+ newParamList[newFeatureCount] = 0;
+ ++newFeatureCount;
+ newFeatureMask |= maskBit;
+ maskBit >>= 1;
+ }
+ }
+ const le_int32* param = addParams;
+ for (const LETag* a = addTags; a != NULL && *a != emptyTag; ++a) {
+ bool add = true;
+ for (le_int32 i = 0; i < fFeatureMapCount; ++i)
+ if (*a == fFeatureMap[i].tag) {
+ if ((fFeatureMask & fFeatureMap[i].mask) != 0)
+ add = false;
+ break;
}
- pTag++;
- pParam++;
+ if (add) {
+ for (const LETag* t = addTags; t != a; ++t)
+ if (*a == *t) {
+ add = false;
+ break;
+ }
}
-
- // terminate the new list
- *dest = emptyTag;
-
- // delete the previous list, unless it was the static default array
- if (fFeatureList != fDefaultFeatures)
- LE_DELETE_ARRAY(fFeatureList);
-
- fFeatureList = newList;
- fFeatureParamList = newParams;
+ if (add) {
+ newFeatureMap[newFeatureCount].tag = *a;
+ newFeatureMap[newFeatureCount].mask = maskBit;
+ if (newParamList != NULL)
+ newParamList[newFeatureCount] = *param++;
+ ++newFeatureCount;
+ newFeatureMask |= maskBit;
+ maskBit >>= 1;
+ }
+ }
+
+ fFeatureMask = newFeatureMask;
+ fFeatureMap = newFeatureMap;
+ fFeatureMapCount = newFeatureCount;
+ fFeatureParamList = newParamList;
}
@@ -264,7 +299,7 @@ void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const le_int32* a
* XeTeXHanLayoutEngine
*/
-const char XeTeXHanLayoutEngine::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(XeTeXHanLayoutEngine)
static const LETag loclFeatureTag = LE_LOCL_FEATURE_TAG;
static const LETag smplFeatureTag = LE_SMPL_FEATURE_TAG;
@@ -272,18 +307,36 @@ static const LETag tradFeatureTag = LE_TRAD_FEATURE_TAG;
static const LETag vertFeatureTag = LE_VERT_FEATURE_TAG;
static const LETag vrt2FeatureTag = LE_VRT2_FEATURE_TAG;
-static const LETag horizontalFeatures[] = {loclFeatureTag, emptyTag};
-static const LETag verticalFeatures[] = {loclFeatureTag, vrt2FeatureTag, vertFeatureTag, emptyTag};
+#define loclFeatureMask 0x80000000UL
+#define smplFeatureMask 0x40000000UL
+#define tradFeatureMask 0x20000000UL
+#define vertFeatureMask 0x10000000UL
+#define vrt2FeatureMask 0x08000000UL
+
+static const FeatureMap featureMap[] = {
+ {loclFeatureTag, loclFeatureMask},
+ {smplFeatureTag, smplFeatureMask},
+ {tradFeatureTag, tradFeatureMask},
+ {vertFeatureTag, vertFeatureMask},
+ {vrt2FeatureTag, vrt2FeatureMask},
+};
+static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap);
+
+#define HORIZ_FEATURES (loclFeatureMask)
+#define VERT_FEATURES (loclFeatureMask|vertFeatureMask|vrt2FeatureMask)
XeTeXHanLayoutEngine::XeTeXHanLayoutEngine(const XeTeXFontInst *fontInstance, LETag scriptTag, LETag languageTag,
- const GlyphSubstitutionTableHeader *gsubTable,
+ const GlyphSubstitutionTableHeader *gsubTable, const GlyphPositioningTableHeader *gposTable,
const LETag *addFeatures, const le_int32* addParams,
const LETag *removeFeatures)
- : XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, NULL, NULL, NULL)
+ : XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, gposTable, NULL, NULL, NULL)
{
- // reset the default feature list
- fFeatureList = fontInstance->getLayoutDirVertical() ? verticalFeatures : horizontalFeatures;
- fDefaultFeatures = fFeatureList;
+ // reset the feature map and default features
+ fFeatureMap = featureMap;
+ fDefaultFeatureMap = fFeatureMap;
+ fFeatureMapCount = featureMapCount;
+
+ fFeatureMask = fontInstance->getLayoutDirVertical() ? VERT_FEATURES : HORIZ_FEATURES;
// then apply any adjustments
adjustFeatures(addFeatures, addParams, removeFeatures);