diff options
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp')
-rw-r--r-- | Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp | 981 |
1 files changed, 404 insertions, 577 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp index eb566b173e4..f01b5b1699e 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp @@ -1,9 +1,10 @@ /****************************************************************************\ Part of the XeTeX typesetting system - copyright (c) 1994-2008 by SIL International - copyright (c) 2009-2012 by Jonathan Kew + Copyright (c) 1994-2008 by SIL International + Copyright (c) 2009-2012 by Jonathan Kew + Copyright (c) 2012 by Khaled Hosny - Written by Jonathan Kew + SIL Author(s): Jonathan Kew Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -30,58 +31,33 @@ use or other dealings in this Software without prior written authorization from the copyright holders. \****************************************************************************/ -#include "unicode/platform.h" // We need this first +#include <unicode/platform.h> // We need this first +#include <unicode/ubidi.h> +#include <unicode/utext.h> #include "XeTeXLayoutInterface.h" - -#include "XeTeXOTLayoutEngine.h" #include "XeTeXFontInst.h" #ifdef XETEX_MAC #include "XeTeXFontInst_Mac.h" #endif #include "XeTeXFontInst_FT2.h" - #include "XeTeXFontMgr.h" - #include "XeTeXswap.h" -#ifdef XETEX_GRAPHITE -#include "XeTeXGrLayout.h" -#endif - -#include "layout/ICUFeatures.h" -#include "layout/ScriptAndLanguage.h" - -#include "unicode/ubidi.h" -#include "unicode/utext.h" - -#include <math.h> -/* apparently M_PI isn't defined by <math.h> under VC++ */ -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - struct XeTeXLayoutEngine_rec - /* this is used for both ICU and Graphite, because so much of the font stuff is common; - however, it is not possible to call ICU-specific things like layoutChars for a - Graphite-based engine, or Graphite functions for an ICU one! */ { - LayoutEngine* layoutEngine; XeTeXFontInst* font; PlatformFontRef fontRef; - UInt32 scriptTag; - UInt32 languageTag; - UInt32* addedFeatures; - UInt32* removedFeatures; + char* script; + char* language; + hb_feature_t* features; + char** shapers; + int nFeatures; UInt32 rgbValue; float extend; float slant; float embolden; -#ifdef XETEX_GRAPHITE - gr::Segment* grSegment; - XeTeXGrFont* grFont; - XeTeXGrTextSource* grSource; -#endif + hb_buffer_t* hbBuffer; }; /*******************************************************************/ @@ -120,17 +96,17 @@ void terminatefontmanager() XeTeXFont createFont(PlatformFontRef fontRef, Fixed pointSize) { - LEErrorCode status = LE_NO_ERROR; + int status = 0; #ifdef XETEX_MAC - XeTeXFontInst* font = new XeTeXFontInst_Mac((ATSFontRef)fontRef, Fix2X(pointSize), status); + XeTeXFontInst* font = new XeTeXFontInst_Mac((ATSFontRef)fontRef, Fix2D(pointSize), status); #else FcChar8* pathname = 0; FcPatternGetString(fontRef, FC_FILE, 0, &pathname); int index; FcPatternGetInteger(fontRef, FC_INDEX, 0, &index); - XeTeXFontInst* font = new XeTeXFontInst_FT2((const char*)pathname, index, Fix2X(pointSize), status); + XeTeXFontInst* font = new XeTeXFontInst_FT2((const char*)pathname, index, Fix2D(pointSize), status); #endif - if (LE_FAILURE(status)) { + if (status != 0) { delete font; return NULL; } @@ -139,9 +115,9 @@ XeTeXFont createFont(PlatformFontRef fontRef, Fixed pointSize) XeTeXFont createFontFromFile(const char* filename, int index, Fixed pointSize) { - LEErrorCode status = LE_NO_ERROR; - XeTeXFontInst* font = new XeTeXFontInst_FT2(filename, index, Fix2X(pointSize), status); - if (LE_FAILURE(status)) { + int status = 0; + XeTeXFontInst* font = new XeTeXFontInst_FT2(filename, index, Fix2D(pointSize), status); + if (status != 0) { delete font; return NULL; } @@ -163,6 +139,11 @@ char getReqEngine() return XeTeXFontMgr::GetFontManager()->getReqEngine(); } +void setReqEngine(char reqEngine) +{ + XeTeXFontMgr::GetFontManager()->setReqEngine(reqEngine); +} + const char* getFullName(PlatformFontRef fontRef) { return XeTeXFontMgr::GetFontManager()->getFullName(fontRef); @@ -201,323 +182,347 @@ void* getFontTablePtr(XeTeXFont font, UInt32 tableTag) Fixed getSlant(XeTeXFont font) { float italAngle = ((XeTeXFontInst*)font)->getItalicAngle(); - return X2Fix(tan(-italAngle * M_PI / 180.0)); + return D2Fix(tan(-italAngle * M_PI / 180.0)); } -static const ScriptListTable* -getLargerScriptListTable(XeTeXFont font) +static UInt32 +getLargerScriptListTable(XeTeXFont font, hb_tag_t** scriptList, hb_tag_t* tableTag) { - const ScriptListTable* scriptListSub = NULL; - const ScriptListTable* scriptListPos = NULL; - - const GlyphSubstitutionTableHeader* gsubTable = (const GlyphSubstitutionTableHeader*)((XeTeXFontInst*)font)->getFontTable(kGSUB); - UInt32 scriptCountSub = 0; - if (gsubTable != NULL) { - scriptListSub = (const ScriptListTable*)((const char*)gsubTable + SWAP(gsubTable->scriptListOffset)); - scriptCountSub = SWAP(scriptListSub->scriptCount); - } + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->hbFont); - const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)((XeTeXFontInst*)font)->getFontTable(kGPOS); - UInt32 scriptCountPos = 0; - if (gposTable != NULL) { - scriptListPos = (const ScriptListTable*)((const char*)gposTable + SWAP(gposTable->scriptListOffset)); - scriptCountPos = SWAP(scriptListPos->scriptCount); - } + hb_tag_t* scriptListSub = NULL; + hb_tag_t* scriptListPos = NULL; + + uint32_t scriptCountSub = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, NULL, NULL); + scriptListSub = (hb_tag_t*) xmalloc(scriptCountSub * sizeof(hb_tag_t*)); + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCountSub, scriptListSub); - return scriptCountPos > scriptCountSub ? scriptListPos : scriptListSub; + uint32_t scriptCountPos = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GPOS, 0, NULL, NULL); + scriptListPos = (hb_tag_t*) xmalloc(scriptCountPos * sizeof(hb_tag_t*)); + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCountPos, scriptListPos); + + if (scriptCountSub > scriptCountPos) { + if (scriptList != NULL) + *scriptList = scriptListSub; + if (tableTag != NULL) + *tableTag = HB_OT_TAG_GSUB; + return scriptCountSub; + } else { + if (scriptList != NULL) + *scriptList = scriptListPos; + if (tableTag != NULL) + *tableTag = HB_OT_TAG_GPOS; + return scriptCountPos; + } } UInt32 countScripts(XeTeXFont font) { - const ScriptListTable* scriptList = getLargerScriptListTable(font); - if (scriptList == NULL) - return 0; - - return SWAP(scriptList->scriptCount); + return getLargerScriptListTable(font, NULL, NULL); } UInt32 getIndScript(XeTeXFont font, UInt32 index) { - const ScriptListTable* scriptList = getLargerScriptListTable(font); + hb_tag_t* scriptList; + + UInt32 scriptCount = getLargerScriptListTable(font, &scriptList, NULL); if (scriptList == NULL) return 0; - if (index < SWAP(scriptList->scriptCount)) - return SWAPT(scriptList->scriptRecordArray[index].tag); + if (index < scriptCount) + return scriptList[index]; return 0; } UInt32 countScriptLanguages(XeTeXFont font, UInt32 script) { - const ScriptListTable* scriptList = getLargerScriptListTable(font); + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->hbFont); + hb_tag_t* scriptList; + hb_tag_t tableTag; + + UInt32 scriptCount = getLargerScriptListTable(font, &scriptList, &tableTag); if (scriptList == NULL) return 0; - const ScriptTable* scriptTable = scriptList->findScript(script); - if (scriptTable == NULL) - return 0; - - UInt32 langCount = SWAP(scriptTable->langSysCount); - - return langCount; + for (int i = 0; i < scriptCount; i++) { + if (scriptList[i] == script) { + return hb_ot_layout_script_get_language_tags (face, tableTag, i, 0, NULL, NULL); + } + } } UInt32 getIndScriptLanguage(XeTeXFont font, UInt32 script, UInt32 index) { - const ScriptListTable* scriptList = getLargerScriptListTable(font); + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->hbFont); + hb_tag_t* scriptList; + hb_tag_t tableTag; + + UInt32 scriptCount = getLargerScriptListTable(font, &scriptList, &tableTag); if (scriptList == NULL) return 0; - const ScriptTable* scriptTable = scriptList->findScript(script); - if (scriptTable == NULL) - return 0; + for (int i = 0; i < scriptCount; i++) { + if (scriptList[i] == script) { + uint32_t langCount = hb_ot_layout_script_get_language_tags(face, tableTag, i, 0, NULL, NULL); + hb_tag_t* langList = (hb_tag_t*) xmalloc(langCount * sizeof(hb_tag_t*)); + hb_ot_layout_script_get_language_tags(face, tableTag, i, 0, &langCount, langList); - if (index < SWAP(scriptTable->langSysCount)) - return SWAPT(scriptTable->langSysRecordArray[index].tag); + if (index < langCount) + return langList[index]; - return 0; + return 0; + } + } } UInt32 countFeatures(XeTeXFont font, UInt32 script, UInt32 language) { - UInt32 total = 0; - const GlyphLookupTableHeader* table; + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->hbFont); + UInt32 total = 0; + for (int i = 0; i < 2; ++i) { - table = (const GlyphLookupTableHeader*)((XeTeXFontInst*)font)->getFontTable(i == 0 ? kGSUB : kGPOS); - if (table != NULL) { - const ScriptListTable* scriptList = (const ScriptListTable*)((const char*)table + SWAP(table->scriptListOffset)); - const ScriptTable* scriptTable = scriptList->findScript(script); - if (scriptTable != NULL) { - const LangSysTable* langTable = scriptTable->findLanguage(language, (language != 0)); - if (langTable != NULL) { - total += SWAP(langTable->featureCount); - if (langTable->reqFeatureIndex != 0xffff) - total += 1; - } + uint32_t scriptIndex, langIndex = 0; + hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; + if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { + if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { + total += hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); } } } - + return total; } UInt32 getIndFeature(XeTeXFont font, UInt32 script, UInt32 language, UInt32 index) { - const GlyphLookupTableHeader* table; - UInt16 featureIndex = 0xffff; + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->hbFont); + for (int i = 0; i < 2; ++i) { - table = (const GlyphLookupTableHeader*)((XeTeXFontInst*)font)->getFontTable(i == 0 ? kGSUB : kGPOS); - if (table != NULL) { - const ScriptListTable* scriptList = (const ScriptListTable*)((const char*)table + SWAP(table->scriptListOffset)); - const ScriptTable* scriptTable = scriptList->findScript(script); - if (scriptTable != NULL) { - const LangSysTable* langTable = scriptTable->findLanguage(language, (language != 0)); - if (langTable != NULL) { - if (SWAP(langTable->reqFeatureIndex) != 0xffff) - if (index == 0) - featureIndex = SWAP(langTable->reqFeatureIndex); - else - index -= 1; - if (index < SWAP(langTable->featureCount)) - featureIndex = SWAP(langTable->featureIndexArray[index]); - index -= SWAP(langTable->featureCount); - } - } - if (featureIndex != 0xffff) { - LETag featureTag; - const FeatureListTable* featureListTable = (const FeatureListTable*)((const char*)table + SWAP(table->featureListOffset)); - (void)featureListTable->getFeatureTable(featureIndex, &featureTag); - return featureTag; + uint32_t scriptIndex, langIndex = 0; + hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; + if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { + if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { + uint32_t featCount = hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); + hb_tag_t* featList = (hb_tag_t*) xmalloc(featCount * sizeof(hb_tag_t*)); + hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, &featCount, featList); + + if (index < featCount) + return featList[index]; + + index -= featCount; } } } - + return 0; } -#ifdef XETEX_GRAPHITE UInt32 countGraphiteFeatures(XeTeXLayoutEngine engine) { - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - UInt32 rval = 0; - while (fi.first != fi.second) { - ++rval; - ++fi.first; - } + uint32_t rval = 0; + + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) + rval = gr_face_n_fref(grFace); + return rval; } UInt32 getGraphiteFeatureCode(XeTeXLayoutEngine engine, UInt32 index) { - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - while (index > 0 && fi.first != fi.second) { - --index; - ++fi.first; + uint32_t rval = 0; + + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_fref(grFace, index); + rval = gr_fref_id(feature); } - if (fi.first != fi.second) - return *fi.first; - return 0; + + return rval; } -UInt32 countGraphiteFeatureSettings(XeTeXLayoutEngine engine, UInt32 feature) +UInt32 countGraphiteFeatureSettings(XeTeXLayoutEngine engine, UInt32 featureID) { - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - while (fi.first != fi.second && *fi.first != feature) - ++fi.first; - if (fi.first != fi.second) { - std::pair<gr::FeatureSettingIterator, gr::FeatureSettingIterator> - si = engine->grFont->getFeatureSettings(fi.first); - UInt32 rval = 0; - while (si.first != si.second) { - ++rval; - ++si.first; - } - return rval; + uint32_t rval = 0; + + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + rval = gr_fref_n_values(feature); } - return 0; + + return rval; } -UInt32 getGraphiteFeatureSettingCode(XeTeXLayoutEngine engine, UInt32 feature, UInt32 index) +UInt32 getGraphiteFeatureSettingCode(XeTeXLayoutEngine engine, UInt32 featureID, UInt32 index) { - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - while (fi.first != fi.second && *fi.first != feature) - ++fi.first; - if (fi.first != fi.second) { - std::pair<gr::FeatureSettingIterator, gr::FeatureSettingIterator> - si = engine->grFont->getFeatureSettings(fi.first); - while (index > 0 && si.first != si.second) { - --index; - ++si.first; - } - if (si.first != si.second) - return *si.first; + uint32_t rval = 0; + + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + rval = gr_fref_value(feature, index); } - return 0; + + return rval; } -UInt32 getGraphiteFeatureDefaultSetting(XeTeXLayoutEngine engine, UInt32 feature) +void getGraphiteFeatureLabel(XeTeXLayoutEngine engine, UInt32 featureID, char* buf) { - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - while (fi.first != fi.second && *fi.first != feature) - ++fi.first; - if (fi.first != fi.second) { - gr::FeatureSettingIterator si = engine->grFont->getDefaultFeatureValue(fi.first); - return *si; + buf[0] = '\0'; + + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + uint32_t len = 0; + uint16_t langID = 0x409; + + buf = (char*) gr_fref_label(feature, &langID, gr_utf8, &len); + + if (len > 128 + 1) { // 128 is set in XeTeX_ext.c + buf = (char*) realloc(buf, len + 1); + buf = (char*) gr_fref_label(feature, &langID, gr_utf8, &len); + } + + buf[len + 1] = '\0'; } - return 0; } -void getGraphiteFeatureLabel(XeTeXLayoutEngine engine, UInt32 feature, unsigned short* buf) +void getGraphiteFeatureSettingLabel(XeTeXLayoutEngine engine, UInt32 featureID, UInt32 settingID, char* buf) { - buf[0] = 0; - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - while (fi.first != fi.second && *fi.first != feature) - ++fi.first; - if (fi.first != fi.second) { - engine->grFont->getFeatureLabel(fi.first, 0x0409, buf); + buf[0] = '\0'; + + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + for (int i = 0; i < gr_fref_n_values(feature); i++) { + if (settingID == gr_fref_value(feature, i)) { + uint32_t len = 0; + uint16_t langID = 0x409; + + buf = (char*) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + + if (len > 128 + 1) { // 128 is set in XeTeX_ext.c + buf = (char*) realloc(buf, len + 1); + buf = (char*) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + } + + buf[len + 1] = '\0'; + break; + } + } } } -void getGraphiteFeatureSettingLabel(XeTeXLayoutEngine engine, UInt32 feature, UInt32 setting, unsigned short* buf) +bool +findGraphiteFeature(XeTeXLayoutEngine engine, const char* s, const char* e, int* f, int* v) + /* s...e is a "feature[=setting]" string; look for this in the font */ { - buf[0] = 0; - std::pair<gr::FeatureIterator, gr::FeatureIterator> fi = engine->grFont->getFeatures(); - while (fi.first != fi.second && *fi.first != feature) - ++fi.first; - if (fi.first != fi.second) { - std::pair<gr::FeatureSettingIterator, gr::FeatureSettingIterator> - si = engine->grFont->getFeatureSettings(fi.first); - while (si.first != si.second && *si.first != setting) - ++si.first; - if (si.first != si.second) { - engine->grFont->getFeatureSettingLabel(si.first, 0x0409, buf); - } - } + *f = 0; + *v = 0; + while (*s == ' ' || *s == '\t') + ++s; + const char* cp = s; + while (cp < e && *cp != '=') + ++cp; + + *f = findGraphiteFeatureNamed(engine, s, cp - s); + if (*f == -1) + return false; + + ++cp; + while (cp < e && (*cp == ' ' || *cp == '\t')) + ++cp; + if (cp >= e) + // no setting was specified, so we just use the first + // XXX the default is not always the first? + return true; + + *v = findGraphiteFeatureSettingNamed(engine, *f, cp, e - cp); + if (*v == -1) + return false; + + return true; } -#endif /* XETEX_GRAPHITE */ long findGraphiteFeatureNamed(XeTeXLayoutEngine engine, const char* name, int namelength) { long rval = -1; -#ifdef XETEX_GRAPHITE - UErrorCode status = (UErrorCode)0; - - std::pair<gr::FeatureIterator,gr::FeatureIterator> features = engine->grFont->getFeatures(); - while (features.first != features.second) { - gr::utf16 label[128]; - if (engine->grFont->getFeatureLabel(features.first, 0x409, &label[0])) { - UText* ut1 = utext_openUTF8(NULL, name, namelength, &status); - UText* ut2 = utext_openUChars(NULL, (const UChar*)&label[0], -1, &status); - UChar32 ch1 = 0, ch2 = 0; - while (ch1 != U_SENTINEL) { - ch1 = utext_next32(ut1); - ch2 = utext_next32(ut2); - if (ch1 != ch2) - break; - } - ut1 = utext_close(ut1); - ut2 = utext_close(ut2); - if (ch1 == ch2) { - rval = *features.first; + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + for (int i = 0; i < gr_face_n_fref(grFace); i++) { + const gr_feature_ref* feature = gr_face_fref(grFace, i); + uint32_t len = 0; + uint16_t langID = 0x409; + + // the first call is to get the length of the string + gr_fref_label(feature, &langID, gr_utf8, &len); + char* label = (char*) xmalloc(len); + label = (char*) gr_fref_label(feature, &langID, gr_utf8, &len); + + if (strncmp(label, name, namelength) == 0) { + rval = gr_fref_id(feature); + gr_label_destroy(label); break; } + + gr_label_destroy(label); } - ++features.first; } -#endif return rval; } -long findGraphiteFeatureSettingNamed(XeTeXLayoutEngine engine, UInt32 feature, const char* name, int namelength) +long findGraphiteFeatureSettingNamed(XeTeXLayoutEngine engine, UInt32 id, const char* name, int namelength) { long rval = -1; -#ifdef XETEX_GRAPHITE - UErrorCode status = (UErrorCode)0; - - std::pair<gr::FeatureIterator,gr::FeatureIterator> features = engine->grFont->getFeatures(); - while (features.first != features.second) { - if (*features.first == feature) { - std::pair<gr::FeatureSettingIterator,gr::FeatureSettingIterator> - settings = engine->grFont->getFeatureSettings(features.first); - while (settings.first != settings.second) { - gr::utf16 label[128]; - if (engine->grFont->getFeatureSettingLabel(settings.first, 0x409, &label[0])) { - UText* ut1 = utext_openUTF8(NULL, name, namelength, &status); - UText* ut2 = utext_openUChars(NULL, (const UChar*)&label[0], -1, &status); - UChar32 ch1 = 0, ch2 = 0; - while (ch1 != U_SENTINEL) { - ch1 = utext_next32(ut1); - ch2 = utext_next32(ut2); - if (ch1 != ch2) - break; - } - ut1 = utext_close(ut1); - ut2 = utext_close(ut2); - if (ch1 == ch2) { - rval = *settings.first; - break; - } - } - ++settings.first; + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, id); + for (int i = 0; i < gr_fref_n_values(feature); i++) { + uint32_t len = 0; + uint16_t langID = 0x409; + + // the first call is to get the length of the string + gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + char* label = (char*) xmalloc(len); + label = (char*) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + + if (strncmp(label, name, namelength) == 0) { + rval = gr_fref_value(feature, i); + gr_label_destroy(label); + break; } - break; + + gr_label_destroy(label); } - ++features.first; } -#endif return rval; } float getGlyphWidth(XeTeXFont font, UInt32 gid) { - LEPoint adv; - ((XeTeXFontInst*)font)->getGlyphAdvance(gid, adv); - return adv.fX; + return ((XeTeXFontInst*)font)->getGlyphWidth(gid); } UInt32 @@ -546,131 +551,134 @@ float getEmboldenFactor(XeTeXLayoutEngine engine) return engine->embolden; } -XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, UInt32 scriptTag, UInt32 languageTag, - UInt32* addFeatures, SInt32* addParams, UInt32* removeFeatures, UInt32 rgbValue, +XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, char* script, char* language, + hb_feature_t* features, int nFeatures, char **shapers, UInt32 rgbValue, float extend, float slant, float embolden) { - LEErrorCode status = LE_NO_ERROR; XeTeXLayoutEngine result = new XeTeXLayoutEngine_rec; result->fontRef = fontRef; result->font = (XeTeXFontInst*)font; - result->scriptTag = scriptTag; - result->languageTag = languageTag; - result->addedFeatures = addFeatures; - result->removedFeatures = removeFeatures; + result->script = script; + result->language = language; + result->features = features; + result->shapers = shapers; + result->nFeatures = nFeatures; result->rgbValue = rgbValue; result->extend = extend; result->slant = slant; result->embolden = embolden; - -#ifdef XETEX_GRAPHITE - result->grSegment = NULL; - result->grSource = NULL; - result->grFont = NULL; -#endif - - result->layoutEngine = XeTeXOTLayoutEngine::LayoutEngineFactory((XeTeXFontInst*)font, scriptTag, languageTag, - (LETag*)addFeatures, (le_int32*)addParams, (LETag*)removeFeatures, status); - if (LE_FAILURE(status) || result->layoutEngine == NULL) { - delete result; - return NULL; - } + result->hbBuffer = hb_buffer_create(); return result; } void deleteLayoutEngine(XeTeXLayoutEngine engine) { - delete engine->layoutEngine; + hb_buffer_destroy(engine->hbBuffer); delete engine->font; -#ifdef XETEX_GRAPHITE - delete engine->grSegment; - delete engine->grSource; - delete engine->grFont; -#endif } -SInt32 layoutChars(XeTeXLayoutEngine engine, UInt16 chars[], SInt32 offset, SInt32 count, SInt32 max, - char rightToLeft, float x, float y, SInt32* status) +int layoutChars(XeTeXLayoutEngine engine, UInt16 chars[], SInt32 offset, SInt32 count, SInt32 max, + bool rightToLeft) { - LEErrorCode success = (LEErrorCode)*status; - le_int32 glyphCount = engine->layoutEngine->layoutChars((const LEUnicode*)chars, - offset, count, max, rightToLeft, x, y, success); - *status = success; - return glyphCount; -} + hb_script_t script = HB_SCRIPT_INVALID; + hb_language_t language = HB_LANGUAGE_INVALID; + hb_direction_t direction = HB_DIRECTION_LTR; -void getGlyphs(XeTeXLayoutEngine engine, UInt32 glyphs[], SInt32* status) -{ - LEErrorCode success = (LEErrorCode)*status; - engine->layoutEngine->getGlyphs((LEGlyphID*)glyphs, success); - *status = success; -} + if (engine->font->getLayoutDirVertical()) + direction = HB_DIRECTION_TTB; + else if (rightToLeft) + direction = HB_DIRECTION_RTL; -void getGlyphPositions(XeTeXLayoutEngine engine, float positions[], SInt32* status) -{ - LEErrorCode success = (LEErrorCode)*status; - engine->layoutEngine->getGlyphPositions(positions, success); + if (engine->script != NULL) + script = hb_script_from_string(engine->script, -1); - if (engine->extend != 1.0 || engine->slant != 0.0) - for (int i = 0; i <= engine->layoutEngine->getGlyphCount(); ++i) - positions[2*i] = positions[2*i] * engine->extend - positions[2*i+1] * engine->slant; + if (engine->language != NULL) + language = hb_language_from_string(engine->language, -1); - *status = success; -} + hb_buffer_reset(engine->hbBuffer); + hb_buffer_add_utf16(engine->hbBuffer, chars, max, offset, count); + hb_buffer_set_direction(engine->hbBuffer, direction); + hb_buffer_set_script(engine->hbBuffer, script); + hb_buffer_set_language(engine->hbBuffer, language); -void getGlyphPosition(XeTeXLayoutEngine engine, SInt32 index, float* x, float* y, SInt32* status) -{ - LEErrorCode success = (LEErrorCode)*status; - engine->layoutEngine->getGlyphPosition(index, *x, *y, success); + hb_shape_full(engine->font->hbFont, engine->hbBuffer, engine->features, engine->nFeatures, engine->shapers); + int glyphCount = hb_buffer_get_length(engine->hbBuffer); - if (engine->extend != 1.0 || engine->slant != 0.0) - *x = *x * engine->extend - *y * engine->slant; +#ifdef DEBUG + char buf[1024]; + unsigned int consumed; + hb_buffer_serialize_flags_t flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; - *status = success; -} + hb_buffer_serialize_glyphs (engine->hbBuffer, 0, glyphCount, buf, sizeof(buf), &consumed, engine->font->hbFont, HB_BUFFER_SERIALIZE_FORMAT_JSON, flags); + if (consumed) + printf ("buffer glyphs: %s\n", buf); +#endif -UInt32 getScriptTag(XeTeXLayoutEngine engine) -{ - return engine->scriptTag; + return glyphCount; } -UInt32 getLanguageTag(XeTeXLayoutEngine engine) +void getGlyphs(XeTeXLayoutEngine engine, UInt32 glyphs[]) { - return engine->languageTag; -} + int glyphCount = hb_buffer_get_length(engine->hbBuffer); + hb_glyph_info_t *hbGlyphs = hb_buffer_get_glyph_infos(engine->hbBuffer, NULL); -float getPointSize(XeTeXLayoutEngine engine) -{ - return engine->font->getXPixelsPerEm(); + for (int i = 0; i < glyphCount; i++) + glyphs[i] = hbGlyphs[i].codepoint; } -void getAscentAndDescent(XeTeXLayoutEngine engine, float* ascent, float* descent) +void getGlyphPositions(XeTeXLayoutEngine engine, float positions[]) { - *ascent = engine->font->getExactAscent(); - *descent = engine->font->getExactDescent(); + int glyphCount = hb_buffer_get_length(engine->hbBuffer); + hb_glyph_position_t *hbPositions = hb_buffer_get_glyph_positions(engine->hbBuffer, NULL); + + int i = 0; + float x = 0, y = 0; + + if (engine->font->getLayoutDirVertical()) { + x -= hbPositions[0].y_offset / 64.0; // hack to compensate offset of 1st glyph + for (i = 0; i < glyphCount; i++) { + positions[2*i] = -(x + hbPositions[i].y_offset / 64.0); /* negative is forwards */ + positions[2*i+1] = (y + hbPositions[i].x_offset / 64.0); + x += hbPositions[i].y_advance / 64.0; + y += hbPositions[i].x_advance / 64.0; + } + positions[2*i] = -x; + positions[2*i+1] = y; + } else { + for (i = 0; i < glyphCount; i++) { + positions[2*i] = x + hbPositions[i].x_offset / 64.0; + positions[2*i+1] = -(y + hbPositions[i].y_offset / 64.0); /* negative is upwards */ + x += hbPositions[i].x_advance / 64.0; + y += hbPositions[i].y_advance / 64.0; + } + positions[2*i] = x; + positions[2*i+1] = -y; + } + + if (engine->extend != 1.0 || engine->slant != 0.0) + for (int i = 0; i <= glyphCount; ++i) + positions[2*i] = positions[2*i] * engine->extend - positions[2*i+1] * engine->slant; } -UInt32* getAddedFeatures(XeTeXLayoutEngine engine) +float getPointSize(XeTeXLayoutEngine engine) { - return engine->addedFeatures; + return engine->font->getPointSize(); } -UInt32* getRemovedFeatures(XeTeXLayoutEngine engine) +void getAscentAndDescent(XeTeXLayoutEngine engine, float* ascent, float* descent) { - return engine->removedFeatures; + *ascent = engine->font->getAscent(); + *descent = engine->font->getDescent(); } int getDefaultDirection(XeTeXLayoutEngine engine) { - switch (engine->scriptTag) { - case kArabic: - case kSyriac: - case kThaana: - case kHebrew: - return UBIDI_DEFAULT_RTL; - } - return UBIDI_DEFAULT_LTR; + hb_script_t script = hb_buffer_get_script(engine->hbBuffer); + if (hb_script_get_horizontal_direction (script) == HB_DIRECTION_RTL) + return UBIDI_DEFAULT_RTL; + else + return UBIDI_DEFAULT_LTR; } UInt32 getRgbValue(XeTeXLayoutEngine engine) @@ -855,282 +863,101 @@ mapGlyphToIndex(XeTeXLayoutEngine engine, const char* glyphName) return engine->font->mapGlyphToIndex(glyphName); } -#ifdef XETEX_MAC -/* this is here rather than XeTeX_mac.c because I want it in a .cpp file */ -int -GetFontCharRange_AAT(ATSUStyle style, int reqFirst) -{ - ATSUFontID fontID; - ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &fontID, 0); - - ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID); - - ByteCount length; - OSStatus status = ATSFontGetTable(fontRef, kCmap, 0, 0, 0, &length); - if (status != noErr) - return 0; - - void* table = LE_NEW_ARRAY(char, length); - status = ATSFontGetTable(fontRef, kCmap, 0, length, table, &length); - if (status != noErr) { - free(table); - return 0; - } - - CMAPMapper* mapper = CMAPMapper::createUnicodeMapper((const CMAPTable *)table); - - int ch = 0; - if (mapper) { - if (reqFirst) - while (mapper->unicodeToGlyph(ch) == 0 && ch < 0x10ffff) - ++ch; - else { - ch = 0x10ffff; - while (mapper->unicodeToGlyph(ch) == 0 && ch > 0) - --ch; - } - delete mapper; - } - else { - LE_DELETE_ARRAY(table); - } - - return ch; - - if (reqFirst) { - int ch = 0; - while (MapCharToGlyph_AAT(style, ch) == 0 && ch < 0x10ffff) - ++ch; - return ch; - } - else { - int ch = 0x10ffff; - while (MapCharToGlyph_AAT(style, ch) == 0 && ch > 0) - --ch; - return ch; - } -} -#endif - -#ifdef XETEX_GRAPHITE +static gr_segment* grSegment = NULL; +static const gr_slot* grPrevSlot = NULL; -/* Graphite interface */ - -gr::LayoutEnvironment layoutEnv; - -XeTeXLayoutEngine createGraphiteEngine(PlatformFontRef fontRef, XeTeXFont font, - const char* name, - UInt32 rgbValue, int rtl, UInt32 languageTag, - float extend, float slant, float embolden, - int nFeatures, const int* featureIDs, const int* featureValues) +bool +initGraphiteBreaking(XeTeXLayoutEngine engine, const UniChar* txtPtr, int txtLen) { - // check if the font supports graphite, and return NULL if not - const UInt32 kttiSilf = 0x53696C66; // from GrConstants.h - if (getFontTablePtr(font, kttiSilf) == NULL) - return NULL; - - XeTeXLayoutEngine result = new XeTeXLayoutEngine_rec; - result->fontRef = fontRef; - result->font = (XeTeXFontInst*)font; - result->scriptTag = 0; - result->languageTag = languageTag; - result->addedFeatures = NULL; - result->removedFeatures = NULL; - result->rgbValue = rgbValue; - result->extend = extend; - result->slant = slant; - result->embolden = embolden; - result->layoutEngine = NULL; + hb_face_t* hbFace = hb_font_get_face(engine->font->hbFont); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + gr_font* grFont = hb_graphite2_font_get_gr_font(engine->font->hbFont); + if (grFace != NULL && grFont != NULL) { + if (grSegment != NULL) { + gr_seg_destroy(grSegment); + grSegment = NULL; + grPrevSlot = NULL; + } - result->grFont = new XeTeXGrFont(result->font, name); + hb_tag_t script = HB_TAG_NONE, lang = HB_TAG_NONE; - result->grSource = new XeTeXGrTextSource(rtl); - result->grSource->setFeatures(nFeatures, featureIDs, featureValues); - if (languageTag != 0) - result->grSource->setLanguage(languageTag); + if (engine->script != NULL) + script = hb_tag_from_string(engine->script, -1); - result->grSegment = NULL; - - layoutEnv.setDumbFallback(true); + if (engine->language != NULL) + lang = hb_tag_from_string(engine->language, -1); - return result; -} + gr_feature_val *grFeatures = gr_face_featureval_for_lang (grFace, lang); -int -makeGraphiteSegment(XeTeXLayoutEngine engine, const UniChar* txtPtr, int txtLen) -{ - if (engine->grSegment) { - delete engine->grSegment; - engine->grSegment = NULL; - } - - engine->grSource->setText(txtPtr, txtLen); - try { - engine->grSegment = new gr::RangeSegment(engine->grFont, engine->grSource, &layoutEnv); - } - catch (gr::FontException f) { - fprintf(stderr, "*** makeGraphiteSegment: font error %d, returning 0\n", (int)f.errorCode); - return 0; - } - catch (...) { - fprintf(stderr, "*** makeGraphiteSegment: segment creation failed, returning 0\n"); - return 0; - } + int nFeatures = engine->nFeatures; + hb_feature_t *features = engine->features; + while (nFeatures--) { + const gr_feature_ref *fref = gr_face_find_fref (grFace, features->tag); + if (fref) + gr_fref_set_feature_value (fref, features->value, grFeatures); + features++; + } - return engine->grSegment->glyphs().second - engine->grSegment->glyphs().first; -} + grSegment = gr_make_seg(grFont, grFace, script, grFeatures, gr_utf16, txtPtr, txtLen, 0); + grPrevSlot = gr_seg_first_slot(grSegment); -void -getGraphiteGlyphInfo(XeTeXLayoutEngine engine, int index, UInt16* glyphID, float* x, float* y) -{ - if (engine->grSegment == NULL) { - *glyphID = 0; - *x = *y = 0.0; - return; + return true; } - gr::GlyphIterator i = engine->grSegment->glyphs().first + index; - *glyphID = i->glyphID(); - if (engine->extend != 1.0 || engine->slant != 0.0) - *x = i->origin() * engine->extend + i->yOffset() * engine->slant; - else - *x = i->origin(); - *y = - i->yOffset(); -} -float -graphiteSegmentWidth(XeTeXLayoutEngine engine) -{ - if (engine->grSegment == NULL) - return 0.0; - //return engine->grSegment->advanceWidth(); // can't use this because it ignores trailing WS - try { - return engine->extend * engine->grSegment->getRangeWidth(0, engine->grSource->getLength(), false, false, false); - } - catch (gr::FontException f) { - fprintf(stderr, "*** graphiteSegmentWidth: font error %d, returning 0.0\n", (int)f.errorCode); - return 0.0; - } - catch (...) { - fprintf(stderr, "*** graphiteSegmentWidth: getRangeWidth failed, returning 0.0\n"); - return 0.0; - } + return false; } -/* line-breaking uses its own private textsource and segment, not the engine's ones */ -static XeTeXGrTextSource* lbSource = NULL; -static gr::Segment* lbSegment = NULL; -static XeTeXLayoutEngine lbEngine = NULL; - -#endif /* XETEX_GRAPHITE */ - -void -initGraphiteBreaking(XeTeXLayoutEngine engine, const UniChar* txtPtr, int txtLen) +int +findNextGraphiteBreak(void) { -#ifdef XETEX_GRAPHITE - if (lbSource == NULL) - lbSource = new XeTeXGrTextSource(0); + if (grSegment == NULL) + return -1; - if (lbSegment != NULL) { - delete lbSegment; - lbSegment = NULL; - } + // XXX: gr_cinfo_base() returns "code unit" index not char index, so this + // is broken outside BMP + if (grPrevSlot && grPrevSlot != gr_seg_last_slot(grSegment)) { + const gr_slot* s; + const gr_char_info* ci = NULL; + for (s = gr_slot_next_in_segment(grPrevSlot); s != NULL; s = gr_slot_next_in_segment(s)) { + int bw; + + ci = gr_seg_cinfo(grSegment, gr_slot_index(s)); + bw = gr_cinfo_break_weight(ci); + if (bw < gr_breakNone && bw >= gr_breakBeforeWord) { + grPrevSlot = s; + return gr_cinfo_base(ci); + } - lbSource->setText(txtPtr, txtLen); - - if (lbEngine != engine) { - gr::FeatureSetting features[64]; - size_t nFeatures = engine->grSource->getFontFeatures(0, features); - lbSource->setFeatures(nFeatures, &features[0]); - lbEngine = engine; - } - - try { - lbSegment = new gr::RangeSegment(engine->grFont, lbSource, &layoutEnv); - } - catch (gr::FontException f) { - fprintf(stderr, "*** initGraphiteBreaking: font error %d\n", (int)f.errorCode); - } - catch (...) { - fprintf(stderr, "*** initGraphiteBreaking: segment creation failed\n"); - } -#endif -} + if (bw > gr_breakNone && bw <= gr_breakWord) { + grPrevSlot = gr_slot_next_in_segment(s); + return gr_cinfo_base(ci) + 1; + } + } -int -findNextGraphiteBreak(int iOffset, int iBrkVal) -{ -#ifdef XETEX_GRAPHITE - if (lbSegment == NULL) + grPrevSlot = gr_seg_last_slot(grSegment); + ci = gr_seg_cinfo(grSegment, gr_slot_after(grPrevSlot)); + return gr_cinfo_base(ci) + 1; + } else { return -1; - if (iOffset < lbSource->getLength()) { - while (++iOffset < lbSource->getLength()) { - const std::pair<gr::GlyphSetIterator,gr::GlyphSetIterator> gsiPair = lbSegment->charToGlyphs(iOffset); - const gr::GlyphSetIterator& gsi = gsiPair.first; - if (gsi == gsiPair.second) - continue; - if (gsi->breakweight() < gr::klbNoBreak && gsi->breakweight() >= -(gr::LineBrk)iBrkVal) - return iOffset; - if (gsi->breakweight() > gr::klbNoBreak && gsi->breakweight() <= (gr::LineBrk)iBrkVal) - return iOffset + 1; - } - return lbSource->getLength(); } - else -#endif - return -1; } int usingGraphite(XeTeXLayoutEngine engine) { -#ifdef XETEX_GRAPHITE - return engine->grFont != NULL; -#else return 0; -#endif } int usingOpenType(XeTeXLayoutEngine engine) { - return engine->layoutEngine != NULL; + return engine->hbBuffer != NULL; } -#define kMATHTableTag 0x4D415448 /* 'MATH' */ - int isOpenTypeMathFont(XeTeXLayoutEngine engine) { - if (engine->layoutEngine != NULL) { - if (engine->font->getFontTable(kMATHTableTag) != NULL) + if (usingOpenType(engine)) { + if (engine->font->getFontTable(kMATH) != NULL) return 1; } return 0; } -int -findGraphiteFeature(XeTeXLayoutEngine engine, const char* s, const char* e, int* f, int* v) - /* s...e is a "feature=setting" string; look for this in the font */ -{ - while (*s == ' ' || *s == '\t') - ++s; - const char* cp = s; - while (cp < e && *cp != '=') - ++cp; - if (cp == e) - return 0; - - *f = findGraphiteFeatureNamed(engine, s, cp - s); - if (*f == -1) - return 0; - - ++cp; - while (cp < e && (*cp == ' ' || *cp == '\t')) - ++cp; - if (cp == e) - return 0; - - *v = findGraphiteFeatureSettingNamed(engine, *f, cp, e - cp); - if (*v == -1) - return 0; - - return 1; -} - |