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.cpp281
1 files changed, 281 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
new file mode 100644
index 00000000000..8eedae283ce
--- /dev/null
+++ b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************\
+ Part of the XeTeX typesetting system
+ copyright (c) 1994-2006 by SIL International
+ written by Jonathan Kew
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL SIL INTERNATIONAL BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of SIL International
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written
+authorization from SIL International.
+\****************************************************************************/
+
+#include "XeTeXOTLayoutEngine.h"
+
+#include "ThaiLayoutEngine.h"
+#include "KhmerLayoutEngine.h"
+
+#include "LEScripts.h"
+#include "LELanguages.h"
+
+const LETag emptyTag = 0x00000000;
+
+static le_int32 getScriptCode(LETag scriptTag)
+{
+ for (le_int32 i = 0; i < scriptCodeCount; ++i)
+ if (OpenTypeLayoutEngine::getScriptTag(i) == scriptTag)
+ return i;
+ return -1;
+}
+
+static le_int32 getLanguageCode(LETag languageTag)
+{
+ for (le_int32 i = 0; i < languageCodeCount; ++i)
+ if (OpenTypeLayoutEngine::getLangSysTag(i) == languageTag)
+ return i;
+ return -1;
+}
+
+LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
+ (const XeTeXFontInst* fontInstance,
+ LETag scriptTag, LETag languageTag,
+ const LETag* addFeatures, const LETag* removeFeatures,
+ LEErrorCode &success)
+{
+ static le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
+
+ if (LE_FAILURE(success))
+ return NULL;
+
+ const GlyphSubstitutionTableHeader* gsubTable = (const GlyphSubstitutionTableHeader*)fontInstance->getFontTable(gsubTableTag);
+ LayoutEngine *result = NULL;
+
+ le_uint32 scriptCode = getScriptCode(scriptTag);
+ le_uint32 languageCode = getLanguageCode(languageTag);
+
+ le_int32 typoFlags = 3;
+
+ if (gsubTable != NULL && gsubTable->coversScript(scriptTag)) {
+ switch (scriptCode) {
+ case bengScriptCode:
+ case devaScriptCode:
+ case gujrScriptCode:
+ case kndaScriptCode:
+ case mlymScriptCode:
+ case oryaScriptCode:
+ case guruScriptCode:
+ case tamlScriptCode:
+ case teluScriptCode:
+// result = new XeTeXIndicLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, removeFeatures);
+ result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
+ break;
+
+ case arabScriptCode:
+ case syrcScriptCode:
+ case mongScriptCode:
+// result = new XeTeXArabicLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, removeFeatures);
+ result = new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
+ break;
+
+ case bopoScriptCode:
+ case haniScriptCode:
+ case hangScriptCode:
+ case hiraScriptCode:
+ case kanaScriptCode:
+ case hrktScriptCode:
+ result = new XeTeXHanLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, removeFeatures);
+ break;
+
+ case khmrScriptCode:
+ result = new KhmerOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable);
+ break;
+
+ default:
+ result = new XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, removeFeatures);
+ break;
+ }
+ }
+ else {
+ switch (scriptCode) {
+ case bengScriptCode:
+ case devaScriptCode:
+ case gujrScriptCode:
+ case kndaScriptCode:
+ case mlymScriptCode:
+ case oryaScriptCode:
+ case guruScriptCode:
+ case tamlScriptCode:
+ case teluScriptCode:
+ result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
+ break;
+
+ case arabScriptCode:
+ case hebrScriptCode:
+ result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
+ break;
+
+ case thaiScriptCode:
+ result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
+ break;
+
+ default:
+ result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
+ break;
+ }
+ }
+
+ if (result == NULL)
+ success = LE_MEMORY_ALLOCATION_ERROR;
+
+ return result;
+}
+
+/*
+ * XeTeXOTLayoutEngine
+ */
+
+const char XeTeXOTLayoutEngine::fgClassID=0;
+
+XeTeXOTLayoutEngine::XeTeXOTLayoutEngine(
+ const LEFontInstance* fontInstance, LETag scriptTag, LETag languageTag,
+ const GlyphSubstitutionTableHeader* gsubTable,
+ const LETag* addFeatures, const LETag* removeFeatures)
+ : OpenTypeLayoutEngine(fontInstance, getScriptCode(scriptTag), getLanguageCode(languageTag), 3, gsubTable)
+{
+ static le_uint32 gposTableTag = LE_GPOS_TABLE_TAG;
+
+ fDefaultFeatures = fFeatureList;
+
+ // check the result of setScriptAndLanguageTags(), in case they were unknown to ICU
+ if (fScriptTag != scriptTag || fLangSysTag != languageTag) {
+ fScriptTag = scriptTag;
+ fLangSysTag = languageTag;
+
+ // 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;
+ }
+ }
+
+ adjustFeatures(addFeatures, removeFeatures);
+}
+
+XeTeXOTLayoutEngine::~XeTeXOTLayoutEngine()
+{
+ if (fFeatureList != NULL && fFeatureList != fDefaultFeatures)
+ LE_DELETE_ARRAY(fFeatureList);
+}
+
+void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const LETag* removeTags)
+{
+ // 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++;
+ }
+
+ // 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;
+ pTag = fFeatureList;
+ while (*pTag != emptyTag) {
+ const LETag* t = removeTags;
+ if (t != NULL)
+ while (*t != emptyTag)
+ if (*t == *pTag)
+ break;
+ else
+ t++;
+ if (t == NULL || *t == emptyTag)
+ *dest++ = *pTag;
+ pTag++;
+ }
+
+ // copy the added tags, skipping any already present
+ pTag = addTags;
+ if (pTag != NULL)
+ while (*pTag != emptyTag) {
+ const LETag* t = newList;
+ while (t < dest)
+ if (*t == *pTag)
+ break;
+ else
+ t++;
+ if (t == dest)
+ *dest++ = *pTag;
+ pTag++;
+ }
+
+ // 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;
+}
+
+
+/*
+ * XeTeXHanLayoutEngine
+ */
+
+const char XeTeXHanLayoutEngine::fgClassID=0;
+
+static const LETag loclFeatureTag = LE_LOCL_FEATURE_TAG;
+static const LETag smplFeatureTag = LE_SMPL_FEATURE_TAG;
+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};
+
+XeTeXHanLayoutEngine::XeTeXHanLayoutEngine(const XeTeXFontInst *fontInstance, LETag scriptTag, LETag languageTag,
+ const GlyphSubstitutionTableHeader *gsubTable,
+ const LETag *addFeatures, const LETag *removeFeatures)
+ : XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, NULL, NULL)
+{
+ // reset the default feature list
+ fFeatureList = fontInstance->getLayoutDirVertical() ? verticalFeatures : horizontalFeatures;
+ fDefaultFeatures = fFeatureList;
+
+ // then apply any adjustments
+ adjustFeatures(addFeatures, removeFeatures);
+}
+
+XeTeXHanLayoutEngine::~XeTeXHanLayoutEngine()
+{
+}