diff options
Diffstat (limited to 'Build/source')
36 files changed, 2183 insertions, 389 deletions
diff --git a/Build/source/libs/icu-xetex/layout/AlternateSubstSubtables.cpp b/Build/source/libs/icu-xetex/layout/AlternateSubstSubtables.cpp index 81989cdd0f1..ffe65b320fe 100644 --- a/Build/source/libs/icu-xetex/layout/AlternateSubstSubtables.cpp +++ b/Build/source/libs/icu-xetex/layout/AlternateSubstSubtables.cpp @@ -27,13 +27,20 @@ le_uint32 AlternateSubstitutionSubtable::process(GlyphIterator *glyphIterator, c Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]); const AlternateSetTable *alternateSetTable = (const AlternateSetTable *) ((char *) this + alternateSetTableOffset); - TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[0]); + le_int32 altIndex = glyphIterator->getFeatureParam(); - if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate))) { - glyphIterator->setCurrGlyphID(SWAPW(alternateSetTable->alternateArray[0])); + if (altIndex < SWAPW(alternateSetTable->glyphCount)) { + TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[altIndex]); + + if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate))) { + glyphIterator->setCurrGlyphID(alternate); + } + + return 1; } - - return 1; + + // feature param was out of range for the glyph + return 0; } // XXXX If we get here, the table's mal-formed... diff --git a/Build/source/libs/icu-xetex/layout/ArabicShaping.cpp b/Build/source/libs/icu-xetex/layout/ArabicShaping.cpp index 0ea6cdbfe0c..36cfd679aa9 100644 --- a/Build/source/libs/icu-xetex/layout/ArabicShaping.cpp +++ b/Build/source/libs/icu-xetex/layout/ArabicShaping.cpp @@ -167,7 +167,7 @@ void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphS LEErrorCode success = LE_NO_ERROR; const LETag *glyphTags = (const LETag *) glyphStorage.getAuxData(outIndex, success); - glyphStorage.setAuxData(outIndex, (void *) &glyphTags[TAGS_PER_GLYPH * shapeOffset], success); + glyphStorage.setAuxData(outIndex, (void *) &glyphTags[TAGS_PER_GLYPH * shapeOffset], NULL, success); } void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax, @@ -232,7 +232,7 @@ void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 char LEUnicode c = chars[in]; ShapeType t = getShapeType(c); - glyphStorage.setAuxData(out, (void *) tagArray, success); + glyphStorage.setAuxData(out, (void *) tagArray, NULL, success); if ((t & MASK_TRANSPARENT) != 0) { continue; diff --git a/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp b/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp index 2c96853ecc8..a68233c21d6 100644 --- a/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp +++ b/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp @@ -19,7 +19,7 @@ GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjus const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader) : direction(1), position(-1), nextLimit(-1), prevLimit(-1), glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments), - srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureTag(theFeatureTag), + srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureTag(theFeatureTag), featureParam(0), glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL) { @@ -53,11 +53,12 @@ GlyphIterator::GlyphIterator(GlyphIterator &that) destIndex = that.destIndex; lookupFlags = that.lookupFlags; featureTag = that.featureTag; + featureParam = that.featureParam; glyphClassDefinitionTable = that.glyphClassDefinitionTable; markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; } -GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag) +GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag, le_int32 newFeatureParam) : glyphStorage(that.glyphStorage) { direction = that.direction; @@ -70,6 +71,7 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag) destIndex = that.destIndex; lookupFlags = that.lookupFlags; featureTag = newFeatureTag; + featureParam = newFeatureParam; glyphClassDefinitionTable = that.glyphClassDefinitionTable; markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; } @@ -87,6 +89,7 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags) destIndex = that.destIndex; lookupFlags = newLookupFlags; featureTag = that.featureTag; + featureParam = that.featureParam; glyphClassDefinitionTable = that.glyphClassDefinitionTable; markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; } @@ -100,6 +103,7 @@ void GlyphIterator::reset(le_uint16 newLookupFlags, LETag newFeatureTag) { position = prevLimit; featureTag = newFeatureTag; + featureParam = 0; lookupFlags = newLookupFlags; } @@ -126,6 +130,11 @@ le_int32 GlyphIterator::getCurrStreamPosition() const return position; } +le_int32 GlyphIterator::getFeatureParam() const +{ + return featureParam; +} + le_bool GlyphIterator::isRightToLeft() const { return direction < 0; @@ -369,9 +378,10 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index) const static const LETag emptyTag = 0; static const LETag defaultTag = 0xFFFFFFFF; -le_bool GlyphIterator::hasFeatureTag() const +le_bool GlyphIterator::hasFeatureTag() { if (featureTag == defaultTag || featureTag == emptyTag) { + featureParam = 0; return TRUE; } @@ -381,6 +391,11 @@ le_bool GlyphIterator::hasFeatureTag() const if (tagList != NULL) { for (le_int32 tag = 0; tagList[tag] != emptyTag; tag += 1) { if (tagList[tag] == featureTag) { + const le_int32 *paramList = (const le_int32 *) glyphStorage.getAuxData2(position, success); + if (paramList != NULL) + featureParam = paramList[tag]; + else + featureParam = 0; return TRUE; } } diff --git a/Build/source/libs/icu-xetex/layout/GlyphIterator.h b/Build/source/libs/icu-xetex/layout/GlyphIterator.h index 93863308d1f..677a0fe6ecb 100644 --- a/Build/source/libs/icu-xetex/layout/GlyphIterator.h +++ b/Build/source/libs/icu-xetex/layout/GlyphIterator.h @@ -28,7 +28,7 @@ public: GlyphIterator(GlyphIterator &that); - GlyphIterator(GlyphIterator &that, LETag newFeatureTag); + GlyphIterator(GlyphIterator &that, LETag newFeatureTag, le_int32 featureParam = 0); GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags); @@ -51,6 +51,8 @@ public: le_int32 getMarkComponent(le_int32 markPosition) const; le_bool findMark2Glyph(); + le_int32 getFeatureParam() const; + void getCursiveEntryPoint(LEPoint &entryPoint) const; void getCursiveExitPoint(LEPoint &exitPoint) const; @@ -72,7 +74,7 @@ public: private: le_bool filterGlyph(le_uint32 index) const; - le_bool hasFeatureTag() const; + le_bool hasFeatureTag(); le_bool nextInternal(le_uint32 delta = 1); le_bool prevInternal(le_uint32 delta = 1); @@ -87,6 +89,7 @@ private: le_int32 destIndex; le_uint16 lookupFlags; LETag featureTag; + le_int32 featureParam; const GlyphClassDefinitionTable *glyphClassDefinitionTable; const MarkAttachClassDefinitionTable *markAttachClassDefinitionTable; diff --git a/Build/source/libs/icu-xetex/layout/HanLayoutEngine.cpp b/Build/source/libs/icu-xetex/layout/HanLayoutEngine.cpp index 23b4a0b28dd..0344f35450a 100644 --- a/Build/source/libs/icu-xetex/layout/HanLayoutEngine.cpp +++ b/Build/source/libs/icu-xetex/layout/HanLayoutEngine.cpp @@ -62,7 +62,7 @@ le_int32 HanOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], l // flag from the language tag lookups, so we can use these features // with the default LangSys... for (le_int32 i = 0; i < count; i += 1) { - glyphStorage.setAuxData(i, (void *) features, success); + glyphStorage.setAuxData(i, (void *) features, NULL, success); } return count; diff --git a/Build/source/libs/icu-xetex/layout/IndicReordering.cpp b/Build/source/libs/icu-xetex/layout/IndicReordering.cpp index 663abc00545..7bae77ecb80 100644 --- a/Build/source/libs/icu-xetex/layout/IndicReordering.cpp +++ b/Build/source/libs/icu-xetex/layout/IndicReordering.cpp @@ -118,7 +118,7 @@ public: fOutChars[fOutIndex] = ch; fGlyphStorage.setCharIndex(fOutIndex, charIndex, success); - fGlyphStorage.setAuxData(fOutIndex, (void *) charTags, success); + fGlyphStorage.setAuxData(fOutIndex, (void *) charTags, NULL, success); fOutIndex += 1; } diff --git a/Build/source/libs/icu-xetex/layout/KhmerReordering.cpp b/Build/source/libs/icu-xetex/layout/KhmerReordering.cpp index 41c56322594..8d1045569a2 100644 --- a/Build/source/libs/icu-xetex/layout/KhmerReordering.cpp +++ b/Build/source/libs/icu-xetex/layout/KhmerReordering.cpp @@ -150,7 +150,7 @@ public: fOutChars[fOutIndex] = ch; fGlyphStorage.setCharIndex(fOutIndex, charIndex, success); - fGlyphStorage.setAuxData(fOutIndex, (void *) charTags, success); + fGlyphStorage.setAuxData(fOutIndex, (void *) charTags, NULL, success); fOutIndex += 1; } diff --git a/Build/source/libs/icu-xetex/layout/LEGlyphStorage.cpp b/Build/source/libs/icu-xetex/layout/LEGlyphStorage.cpp index 7cffc732216..55cbbbfcb21 100644 --- a/Build/source/libs/icu-xetex/layout/LEGlyphStorage.cpp +++ b/Build/source/libs/icu-xetex/layout/LEGlyphStorage.cpp @@ -15,7 +15,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage) LEGlyphStorage::LEGlyphStorage() : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL), - fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0) + fAuxData(NULL), fAuxParam(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0) { // nothing else to do! } @@ -38,6 +38,10 @@ void LEGlyphStorage::reset() LE_DELETE_ARRAY(fAuxData); fAuxData = NULL; } + if (fAuxParam != NULL) { + LE_DELETE_ARRAY(fAuxParam); + fAuxParam = NULL; + } if (fInsertionList != NULL) { delete fInsertionList; @@ -136,8 +140,9 @@ le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success) } fAuxData = LE_NEW_ARRAY(void *, fGlyphCount); + fAuxParam = LE_NEW_ARRAY(void *, fGlyphCount); - if (fAuxData == NULL) { + if (fAuxData == NULL || fAuxParam == NULL) { success = LE_MEMORY_ALLOCATION_ERROR; return -1; } @@ -344,13 +349,32 @@ void *LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) cons return fAuxData[glyphIndex]; } -void LEGlyphStorage::setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode &success) +void *LEGlyphStorage::getAuxData2(le_int32 glyphIndex, LEErrorCode &success) const +{ + if (LE_FAILURE(success)) { + return NULL; + } + + if (fAuxParam == NULL) { + success = LE_NO_LAYOUT_ERROR; + return NULL; + } + + if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return NULL; + } + + return fAuxParam[glyphIndex]; +} + +void LEGlyphStorage::setAuxData(le_int32 glyphIndex, void *auxData, void *auxParam, LEErrorCode &success) { if (LE_FAILURE(success)) { return; } - if (fAuxData == NULL) { + if (fAuxData == NULL || fAuxParam == NULL) { success = LE_NO_LAYOUT_ERROR; return; } @@ -361,6 +385,7 @@ void LEGlyphStorage::setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode } fAuxData[glyphIndex] = auxData; + fAuxParam[glyphIndex] = auxParam; } void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const @@ -469,14 +494,19 @@ void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from) from.fPositions = NULL; } -void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from) +void LEGlyphStorage::adoptAuxDataArrays(LEGlyphStorage &from) { if (fAuxData != NULL) { LE_DELETE_ARRAY(fAuxData); } + if (fAuxParam != NULL) { + LE_DELETE_ARRAY(fAuxParam); + } fAuxData = from.fAuxData; from.fAuxData = NULL; + fAuxParam = from.fAuxParam; + from.fAuxParam = NULL; } void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from) @@ -511,6 +541,9 @@ le_int32 LEGlyphStorage::applyInsertions() if (fAuxData != NULL) { fAuxData = (void **) LE_GROW_ARRAY(fAuxData, newGlyphCount); } + if (fAuxParam != NULL) { + fAuxParam = (void **) LE_GROW_ARRAY(fAuxParam, newGlyphCount); + } fSrcIndex = fGlyphCount - 1; fDestIndex = newGlyphCount - 1; @@ -564,6 +597,18 @@ le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGl } } + if (fAuxParam != NULL) { + le_int32 src = fSrcIndex, dest = fDestIndex; + + while (src > atPosition) { + fAuxParam[dest--] = fAuxParam[src--]; + } + + for (le_int32 i = count - 1; i >= 0; i -= 1) { + fAuxParam[dest--] = fAuxParam[atPosition]; + } + } + while (fSrcIndex > atPosition) { fGlyphs[fDestIndex] = fGlyphs[fSrcIndex]; fCharIndices[fDestIndex] = fCharIndices[fSrcIndex]; diff --git a/Build/source/libs/icu-xetex/layout/LEGlyphStorage.h b/Build/source/libs/icu-xetex/layout/LEGlyphStorage.h index 845ff12146f..34e3f3df93b 100644 --- a/Build/source/libs/icu-xetex/layout/LEGlyphStorage.h +++ b/Build/source/libs/icu-xetex/layout/LEGlyphStorage.h @@ -63,11 +63,12 @@ private: float *fPositions; /** - * The auxillary data array. + * The auxiliary data arrays. * * @internal */ void **fAuxData; + void **fAuxParam; /** @@ -295,6 +296,7 @@ public: * @draft ICU 3.0 */ void *getAuxData(le_int32 glyphIndex, LEErrorCode &success) const; + void *getAuxData2(le_int32 glyphIndex, LEErrorCode &success) const; /** * This operator allows direct access to the glyph array @@ -387,15 +389,16 @@ public: void adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success); /** - * Set the auxillary data for a particular glyph. + * Set the auxiliary data for a particular glyph. * * @param glyphIndex the index of the glyph - * @param auxData the new auxillary data - * @param success will be set to an error code if the auxillary data cannot be set. + * @param auxData the new auxiliary data + * @param auxParam the new secondary auxiliary data (parameter) + * @param success will be set to an error code if the auxiliary data cannot be set. * * @draft ICU 3.0 */ - void setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode &success); + void setAuxData(le_int32 glyphIndex, void *auxData, void *auxParam, LEErrorCode &success); /** * Delete the glyph array and replace it with the one @@ -443,7 +446,7 @@ public: * * @draft ICU 3.0 */ - void adoptAuxDataArray(LEGlyphStorage &from); + void adoptAuxDataArrays(LEGlyphStorage &from); /** * Change the glyph count of this object to be the same diff --git a/Build/source/libs/icu-xetex/layout/LayoutEngine.cpp b/Build/source/libs/icu-xetex/layout/LayoutEngine.cpp index eff598cf280..3bfb6c9d96b 100644 --- a/Build/source/libs/icu-xetex/layout/LayoutEngine.cpp +++ b/Build/source/libs/icu-xetex/layout/LayoutEngine.cpp @@ -211,7 +211,7 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off for (i = 0; i < count; i += 1, out += dir) { glyphStorage[out] = (LEGlyphID) inChars[i]; - glyphStorage.setAuxData(out, (void *) canonFeatures, success); + glyphStorage.setAuxData(out, (void *) canonFeatures, NULL, success); } if (reordered != NULL) { diff --git a/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.cpp b/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.cpp index 6df05c19312..2d1e3dde84a 100644 --- a/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.cpp +++ b/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.cpp @@ -57,7 +57,8 @@ static const LETag kernAndLigaFeatures[] = {ccmpFeatureTag, loclFeatureTag, liga OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable) - : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags), fFeatureList(minimalFeatures), fFeatureOrder(NULL), + : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags), + fFeatureList(minimalFeatures), fFeatureParamList(NULL), fFeatureOrder(NULL), fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; @@ -148,9 +149,8 @@ le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_i glyphStorage.allocateGlyphArray(outCharCount, rightToLeft, success); glyphStorage.allocateAuxData(success); - for (le_int32 i = 0; i < outCharCount; i += 1) { - glyphStorage.setAuxData(i, (void *) fFeatureList, success); + glyphStorage.setAuxData(i, (void *) fFeatureList, (void *) fFeatureParamList, success); } return outCharCount; @@ -191,7 +191,7 @@ le_int32 OpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStor glyphStorage.adoptGlyphArray(tempGlyphStorage); glyphStorage.adoptCharIndicesArray(tempGlyphStorage); - glyphStorage.adoptAuxDataArray(tempGlyphStorage); + glyphStorage.adoptAuxDataArrays(tempGlyphStorage); glyphStorage.adoptGlyphCount(tempGlyphStorage); return glyphStorage.getGlyphCount(); diff --git a/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.h b/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.h index fd6dfac2b23..6f9d4839f5b 100644 --- a/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.h +++ b/Build/source/libs/icu-xetex/layout/OpenTypeLayoutEngine.h @@ -151,6 +151,7 @@ protected: * @internal */ const LETag *fFeatureList; + const le_int32 *fFeatureParamList; /** * A list of tags in the order in which the features in diff --git a/Build/source/libs/icu-xetex/layout/PairPositioningSubtables.cpp b/Build/source/libs/icu-xetex/layout/PairPositioningSubtables.cpp index 6994b9aeace..e9b2c7c76b0 100644 --- a/Build/source/libs/icu-xetex/layout/PairPositioningSubtables.cpp +++ b/Build/source/libs/icu-xetex/layout/PairPositioningSubtables.cpp @@ -48,14 +48,14 @@ le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, le_int32 coverageIndex = getGlyphCoverage(firstGlyph); GlyphIterator tempIterator(*glyphIterator); - if (coverageIndex >= 0 && glyphIterator->next()) { + if (coverageIndex >= 0 && tempIterator.next()) { Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]); PairSetTable *pairSetTable = (PairSetTable *) ((char *) this + pairSetTableOffset); le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount); le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1)); le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2)); le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size; - LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID(); + LEGlyphID secondGlyph = tempIterator.getCurrGlyphID(); const PairValueRecord *pairValueRecord = NULL; if (pairValueCount != 0) { @@ -67,16 +67,16 @@ le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, } if (valueFormat1 != 0) { - pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance); + pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, *glyphIterator, fontInstance); } if (valueFormat2 != 0) { const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size); - valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, *glyphIterator, fontInstance); + valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, tempIterator, fontInstance); } - return 0; + return 1; } return 0; @@ -88,8 +88,8 @@ le_uint32 PairPositioningFormat2Subtable::process(GlyphIterator *glyphIterator, le_int32 coverageIndex = getGlyphCoverage(firstGlyph); GlyphIterator tempIterator(*glyphIterator); - if (coverageIndex >= 0 && glyphIterator->next()) { - LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID(); + if (coverageIndex >= 0 && tempIterator.next()) { + LEGlyphID secondGlyph = tempIterator.getCurrGlyphID(); const ClassDefinitionTable *classDef1 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef1Offset)); const ClassDefinitionTable *classDef2 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef2Offset)); le_int32 class1 = classDef1->getGlyphClass(firstGlyph); @@ -103,16 +103,16 @@ le_uint32 PairPositioningFormat2Subtable::process(GlyphIterator *glyphIterator, if (valueFormat1 != 0) { - class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance); + class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, *glyphIterator, fontInstance); } if (valueFormat2 != 0) { const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size); - valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, *glyphIterator, fontInstance); + valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, tempIterator, fontInstance); } - return 0; + return 1; } return 0; diff --git a/Build/source/texk/web2c/configure.in b/Build/source/texk/web2c/configure.in index b350439f8d9..7c4623a32cf 100644 --- a/Build/source/texk/web2c/configure.in +++ b/Build/source/texk/web2c/configure.in @@ -95,8 +95,11 @@ sinclude(../../libs/libpng/withenable.ac) sinclude(../../libs/zlib/zlib.ac) sinclude(../../libs/libpng/libpng.ac) sinclude(../../libs/xpdf/libxpdf.ac) +sinclude(../../libs/freetype2/withenable.ac) sinclude(../../libs/freetype2/freetype2.ac) +sinclude(../../libs/teckit/withenable.ac) sinclude(../../libs/teckit/teckit.ac) +sinclude(../../libs/icu-xetex/withenable.ac) sinclude(../../libs/icu-xetex/icu-xetex.ac) # Whether to build mf-nowin. @@ -175,19 +178,6 @@ else with_xetex=no fi -sinclude(xetexdir/tests.ac) -AC_HAS_CARBON - -if test "x$has_carbon" = "xyes"; then - XETEX_MACOSX= - XETEX_GENERIC='#! ' -else - XETEX_MACOSX='#! ' - XETEX_GENERIC= -fi -AC_SUBST(XETEX_MACOSX) -AC_SUBST(XETEX_GENERIC) - # Check whether C++ compiler works. Prevent exit if it doesn't. if test "x$with_pdftex" = xyes || test "x$with_pdfetex" = xyes || @@ -225,7 +215,8 @@ CXXHACKLINK='$(kpathsea_cxx_link)' CXXHACKLDLIBS='$(LOADLIBES)' if test "x$with_cxx_runtime_hack" = xyes && { test "x$with_pdftex" = xyes || - test "x$with_pdfetex" = xyes; } + test "x$with_pdfetex" = xyes || + test "x$with_xetex" = xyes; } then AC_MSG_CHECKING(for statically linking C++ runtime library) @@ -296,6 +287,19 @@ else fi AC_SUBST(XETEX) +sinclude(xetexdir/tests.ac) +AC_HAS_CARBON + +if test "x$has_carbon" = "xyes"; then + XETEX_MACOSX= + XETEX_GENERIC='#! ' +else + XETEX_MACOSX='#! ' + XETEX_GENERIC= +fi +AC_SUBST(XETEX_MACOSX) +AC_SUBST(XETEX_GENERIC) + # For e-TeX, three choices: no, yes, and tex. In the latter case, we # have to comment out the normal TeX build (TEX), as well as enable the # e-TeX build (ETEX) and the replacement of TeX with e-TeX in compatibilty @@ -395,7 +399,7 @@ KPSE_CROSS_PATH_PROG(TANGLE, tangle, ./tangle) KPSE_CROSS_PATH_PROG(CTANGLEBOOT, ctangle, ./ctangleboot) KPSE_CROSS_PATH_PROG(CTANGLE, ctangle, ./ctangle) KPSE_CROSS_PATH_PROG(TIE, tie, ./tie) -if test "x$with_omega" = xyes || test "x$with_aleph" = xyes; then +if test "x$with_omega" = xyes || test "x$with_aleph" = xyes || test "x$with_xetex" = xyes; then KPSE_CROSS_PATH_PROG(OTANGLE, otangle, ./otangle) fi diff --git a/Build/source/texk/web2c/xetexdir/MathTable.h b/Build/source/texk/web2c/xetexdir/MathTable.h new file mode 100644 index 00000000000..1c27a67fee0 --- /dev/null +++ b/Build/source/texk/web2c/xetexdir/MathTable.h @@ -0,0 +1,219 @@ +/****************************************************************************\ + 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. +\****************************************************************************/ + +#ifndef __MATHTABLE_H__ +#define __MATHTABLE_H__ + +#include "OpenTypeTables.h" + +typedef struct { + le_int16 value; + le_uint16 deviceTable; +} MathValueRecord; + +typedef struct { + le_uint32 version; + le_uint16 mathConstants; + le_uint16 mathGlyphInfo; + le_uint16 mathVariants; +} MathTableHeader; + +typedef struct { + le_uint16 scriptPercentScaleDown; + le_uint16 scriptScriptPercentScaleDown; + le_uint16 delimitedSubFormulaMinHeight; + le_uint16 displayOperatorMinHeight; + MathValueRecord mathLeading; + MathValueRecord axisHeight; + MathValueRecord accentBaseHeight; + MathValueRecord flattenedAccentBaseHeight; + MathValueRecord subscriptShiftDown; + MathValueRecord subscriptTopMax; + MathValueRecord subscriptBaselineDropMin; + MathValueRecord superscriptShiftUp; + MathValueRecord superscriptShiftUpCramped; + MathValueRecord superscriptBottomMin; + MathValueRecord superscriptBaselineDropMax; + MathValueRecord subSuperscriptGapMin; + MathValueRecord superscriptBottomMaxWithSubscript; + MathValueRecord spaceAfterScript; + MathValueRecord upperLimitGapMin; + MathValueRecord upperLimitBaselineRiseMin; + MathValueRecord lowerLimitGapMin; + MathValueRecord lowerLimitBaselineDropMin; + MathValueRecord stackTopShiftUp; + MathValueRecord stackTopDisplayStyleShiftUp; + MathValueRecord stackBottomShiftDown; + MathValueRecord stackBottomDisplayStyleShiftDown; + MathValueRecord stackGapMin; + MathValueRecord stackDisplayStyleGapMin; + MathValueRecord stretchStackTopShiftUp; + MathValueRecord stretchStackBottomShiftDown; + MathValueRecord stretchStackGapAboveMin; + MathValueRecord stretchStackGapBelowMin; + MathValueRecord fractionNumeratorShiftUp; + MathValueRecord fractionNumeratorDisplayStyleShiftUp; + MathValueRecord fractionDenominatorShiftDown; + MathValueRecord fractionDenominatorDisplayStyleShiftDown; + MathValueRecord fractionNumeratorGapMin; + MathValueRecord fractionNumDiisplayStyleGapMin; + MathValueRecord fractionRuleThickness; + MathValueRecord fractionDenominatorGapMin; + MathValueRecord fractionDenomDisplayStyleGapMin; + MathValueRecord skewedFractionHorizontalGap; + MathValueRecord skewedFractionVerticalGap; + MathValueRecord overbarVerticalGap; + MathValueRecord overbarRuleThickness; + MathValueRecord overbarExtraAscender; + MathValueRecord underbarVerticalGap; + MathValueRecord underbarRuleThickness; + MathValueRecord underbarExtraDescender; + MathValueRecord radicalVerticalGap; + MathValueRecord radicalDisplayStyleVerticalGap; + MathValueRecord radicalRuleThickness; + MathValueRecord radicalExtraAscender; + MathValueRecord radicalKernBeforeDegree; + MathValueRecord radicalKernAfterDegree; + le_uint16 radicalDegreeBottomRaisePercent; +} MathConstants; + +typedef enum { + unknown = -1, + scriptPercentScaleDown = 0, + scriptScriptPercentScaleDown, + delimitedSubFormulaMinHeight, + displayOperatorMinHeight, + mathLeading, + firstMathValueRecord = mathLeading, + axisHeight, + accentBaseHeight, + flattenedAccentBaseHeight, + subscriptShiftDown, + subscriptTopMax, + subscriptBaselineDropMin, + superscriptShiftUp, + superscriptShiftUpCramped, + superscriptBottomMin, + superscriptBaselineDropMax, + subSuperscriptGapMin, + superscriptBottomMaxWithSubscript, + spaceAfterScript, + upperLimitGapMin, + upperLimitBaselineRiseMin, + lowerLimitGapMin, + lowerLimitBaselineDropMin, + stackTopShiftUp, + stackTopDisplayStyleShiftUp, + stackBottomShiftDown, + stackBottomDisplayStyleShiftDown, + stackGapMin, + stackDisplayStyleGapMin, + stretchStackTopShiftUp, + stretchStackBottomShiftDown, + stretchStackGapAboveMin, + stretchStackGapBelowMin, + fractionNumeratorShiftUp, + fractionNumeratorDisplayStyleShiftUp, + fractionDenominatorShiftDown, + fractionDenominatorDisplayStyleShiftDown, + fractionNumeratorGapMin, + fractionNumDisplayStyleGapMin, + fractionRuleThickness, + fractionDenominatorGapMin, + fractionDenomDisplayStyleGapMin, + skewedFractionHorizontalGap, + skewedFractionVerticalGap, + overbarVerticalGap, + overbarRuleThickness, + overbarExtraAscender, + underbarVerticalGap, + underbarRuleThickness, + underbarExtraDescender, + radicalVerticalGap, + radicalDisplayStyleVerticalGap, + radicalRuleThickness, + radicalExtraAscender, + radicalKernBeforeDegree, + radicalKernAfterDegree, + lastMathValueRecord = radicalKernAfterDegree, + radicalDegreeBottomRaisePercent, + lastMathConstant = radicalDegreeBottomRaisePercent +} mathConstantIndex; + +typedef struct { + le_uint16 minConnectorOverlap; + Offset vertGlyphCoverage; + Offset horizGlyphCoverage; + le_uint16 vertGlyphCount; + le_uint16 horizGlyphCount; + Offset vertGlyphConstruction[ANY_NUMBER]; + Offset horizGlyphConstruction[ANY_NUMBER]; +} MathVariants; + +typedef struct { + TTGlyphID variantGlyph; + le_uint16 advanceMeasurement; +} MathGlyphVariantRecord; + +typedef struct { + Offset glyphAssembly; + le_uint16 variantCount; + MathGlyphVariantRecord mathGlyphVariantRecord[ANY_NUMBER]; +} MathGlyphConstruction; + +typedef struct { + TTGlyphID glyph; + le_uint16 startConnectorLength; + le_uint16 endConnectorLength; + le_uint16 fullAdvance; + le_uint16 partFlags; +} GlyphPartRecord; +#define fExtender 0x0001 + +typedef struct { + MathValueRecord italicsCorrection; + le_uint16 partCount; + GlyphPartRecord partRecords[ANY_NUMBER]; +} GlyphAssembly; + +typedef struct { + le_uint16 mathItalicsCorrectionInfo; + le_uint16 mathTopAccentAttachment; + le_uint16 extendedShapeCoverage; + le_uint16 mathKernInfo; +} MathGlyphInfo; + +typedef struct { + le_uint16 coverage; + le_uint16 italicsCorrectionCount; + MathValueRecord italicsCorrection[ANY_NUMBER]; +} MathItalicsCorrectionInfo; + +#endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp index c598b9c96a1..fc21a6837a0 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp @@ -71,6 +71,8 @@ XeTeXFontInst::XeTeXFontInst(float pointSize, LEErrorCode &status) , fNumGlyphsInited(false) , fVertical(false) , fFilename(NULL) + , fFirstCharCode(-1) + , fLastCharCode(-1) { // the concrete subclass is responsible to call initialize() } @@ -296,3 +298,37 @@ XeTeXFontInst::mapGlyphToIndex(const char* glyphName) const else return 0; } + +const char* +XeTeXFontInst::getGlyphName(LEGlyphID gid, int& nameLen) +{ + le_uint32 len; + const char *p = (const char*)readFontTable(LE_POST_TABLE_TAG, len); + if (p != NULL) { + return getGlyphNamePtr(p, len, gid, &nameLen); + } +} + +LEUnicode32 +XeTeXFontInst::getFirstCharCode() +{ + if (fFirstCharCode == -1) { + int ch = 0; + while (mapCharToGlyph(ch) == 0 && ch < 0x10ffff) + ++ch; + fFirstCharCode = ch; + } + return fFirstCharCode; +} + +LEUnicode32 +XeTeXFontInst::getLastCharCode() +{ + if (fLastCharCode == -1) { + int ch = 0x10ffff; + while (mapCharToGlyph(ch) == 0 && ch > 0) + --ch; + fLastCharCode = ch; + } + return fLastCharCode; +} diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h index a30d7c4b238..b20f6d5ab40 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h @@ -88,6 +88,9 @@ protected: char *fFilename; // actually holds [filename:index], as used in xetex + int fFirstCharCode; + int fLastCharCode; + virtual const void *readTable(LETag tag, le_uint32 *length) const = 0; void deleteTable(const void *table) const; void getMetrics(); @@ -173,6 +176,11 @@ public: void getGlyphSidebearings(LEGlyphID glyph, float* lsb, float* rsb); float getGlyphItalCorr(LEGlyphID glyph); + virtual const char* getGlyphName(LEGlyphID gid, int& nameLen); + + virtual LEUnicode32 getFirstCharCode(); + virtual LEUnicode32 getLastCharCode(); + float getXPixelsPerEm() const { return fPointSize; diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.cpp index cc56442be24..9b909057259 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.cpp @@ -232,3 +232,48 @@ XeTeXFontInst_FT2::getKernPair(LEGlyphID leftGlyph, LEGlyphID rightGlyph, LEPoin else kern.fX = kern.fY = 0; } + +const char* +XeTeXFontInst_FT2::getGlyphName(LEGlyphID gid, int& nameLen) +{ + if (!fFreeTypeOnly) + return XeTeXFontInst::getGlyphName(gid, nameLen); + else if (FT_HAS_GLYPH_NAMES(face)) { + static char buffer[256]; + FT_Get_Glyph_Name(face, gid, buffer, 256); + nameLen = strlen(buffer); + return &buffer[0]; + } + else { + nameLen = 0; + return NULL; + } +} + +LEUnicode32 +XeTeXFontInst_FT2::getFirstCharCode() +{ + if (!fFreeTypeOnly) + return XeTeXFontInst::getFirstCharCode(); + else { + FT_UInt gindex; + return FT_Get_First_Char(face, &gindex); + } +} + +LEUnicode32 +XeTeXFontInst_FT2::getLastCharCode() +{ + if (!fFreeTypeOnly) + return XeTeXFontInst::getLastCharCode(); + else { + FT_UInt gindex; + LEUnicode32 ch = FT_Get_First_Char(face, &gindex); + LEUnicode32 prev = ch; + while (gindex != 0) { + prev = ch; + ch = FT_Get_Next_Char(face, ch, &gindex); + } + return prev; + } +} diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.h b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.h index fb439114ab9..217d6e5ca4c 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_FT2.h @@ -68,6 +68,9 @@ public: virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const; virtual LEGlyphID mapGlyphToIndex(const char* glyphName) const; virtual void getKernPair(LEGlyphID leftGlyph, LEGlyphID rightGlyph, LEPoint &kern) const; + virtual const char* getGlyphName(LEGlyphID gid, int& nameLen); + virtual LEUnicode32 getFirstCharCode(); + virtual LEUnicode32 getLastCharCode(); }; #endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp index 63d9567222f..ebcf270eb47 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp @@ -320,7 +320,10 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) // try for more boldness, with the same width and slant Font* bestMatch = font; if (font->weight < parent->maxWeight) { - bestMatch = bestMatchFromFamily(parent, parent->maxWeight, font->width, font->slant); + // try to increase weight by 1/2 x (max - min), rounding up + bestMatch = bestMatchFromFamily(parent, + font->weight + (parent->maxWeight - parent->minWeight) / 2 + 1, + font->width, font->slant); if (parent->minSlant == parent->maxSlant) { // double-check the italic flag, as we can't trust slant values Font* newBest = NULL; @@ -445,12 +448,21 @@ XeTeXFontMgr::getOpSizeRecAndStyleFlags(Font* theFont) if (font != 0) { const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)getFontTablePtr(font, LE_GPOS_TABLE_TAG); if (gposTable != NULL) { - FeatureListTable* featureListTable = (FeatureListTable*)((char*)gposTable + SWAP(gposTable->featureListOffset)); + const FeatureListTable* featureListTable = (const FeatureListTable*)((const char*)gposTable + SWAP(gposTable->featureListOffset)); for (int i = 0; i < SWAP(featureListTable->featureCount); ++i) { UInt32 tag = SWAPT(featureListTable->featureRecordArray[i].featureTag); if (tag == LE_SIZE_FEATURE_TAG) { - FeatureTable* feature = (FeatureTable*)((char*)featureListTable + SWAP(featureListTable->featureRecordArray[i].featureTableOffset)); - OpSizeRec* pSizeRec = (OpSizeRec*)((char*)featureListTable + SWAP(feature->featureParamsOffset)); + const FeatureTable* feature = (const FeatureTable*)((const char*)featureListTable + + SWAP(featureListTable->featureRecordArray[i].featureTableOffset)); + UInt16 offset = SWAP(feature->featureParamsOffset); + const OpSizeRec* pSizeRec; + /* if featureParamsOffset < (offset of feature from featureListTable), + then we have a correct size table; + otherwise we (presumably) have a "broken" one from the old FDK */ + if (offset < (const char*)feature - (const char*)featureListTable) + pSizeRec = (const OpSizeRec*)((char*)feature + offset); + else + pSizeRec = (const OpSizeRec*)((char*)featureListTable + offset); theFont->opSizeInfo.designSize = SWAP(pSizeRec->designSize); theFont->opSizeInfo.subFamilyID = SWAP(pSizeRec->subFamilyID); theFont->opSizeInfo.nameCode = SWAP(pSizeRec->nameCode); diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp index 89bae840bac..f0f714568ea 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp @@ -333,7 +333,7 @@ XeTeXFont getFont(XeTeXLayoutEngine engine) } XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, UInt32 scriptTag, UInt32 languageTag, - UInt32* addFeatures, UInt32* removeFeatures, UInt32 rgbValue) + UInt32* addFeatures, SInt32* addParams, UInt32* removeFeatures, UInt32 rgbValue) { LEErrorCode status = LE_NO_ERROR; XeTeXLayoutEngine result = new XeTeXLayoutEngine_rec; @@ -344,8 +344,8 @@ XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, UI result->addedFeatures = addFeatures; result->removedFeatures = removeFeatures; result->rgbValue = rgbValue; - result->layoutEngine = XeTeXOTLayoutEngine::LayoutEngineFactory((XeTeXFontInst*)font, - scriptTag, languageTag, (LETag*)addFeatures, (LETag*)removeFeatures, status); + 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; @@ -528,8 +528,138 @@ findGlyphInPostTable(const char* buffer, int tableSize, const char* glyphName) return 0; } +const char* +getGlyphNamePtr(const char* buffer, int tableSize, UInt16 gid, int* len) +{ + const postTable* p = (const postTable*)buffer; + switch (SWAP(p->format)) { + case 0x00010000: + { + if (gid < 258) { + *len = strlen(appleGlyphNames[gid]); + return appleGlyphNames[gid]; + } + } + break; + + case 0x00020000: + { + const UInt16* n = (UInt16*)(p + 1); + UInt16 numGlyphs = SWAP(*n++); + const UInt8* ps = (const UInt8*)(n + numGlyphs); + std::vector<const UInt8*> namePtrs; + while (ps < (const UInt8*)buffer + tableSize) { + namePtrs.push_back(ps); + ps += *ps + 1; + } + if (gid < numGlyphs) { + gid = SWAP(n[gid]); + if (gid < 258) { + *len = strlen(appleGlyphNames[gid]); + return appleGlyphNames[gid]; + } + else { + ps = namePtrs[gid - 258]; + *len = *ps; + return (char*)(ps + 1); + } + } + } + break; + + case 0x00028000: + break; + + case 0x00030000: + // TODO: see if it's a CFF OpenType font, and if so, get the glyph names from the CFF data + break; + + case 0x00040000: + break; + + default: + break; + } + + /* no name found */ + *len = 0; + return NULL; +} + +int +getFontCharRange(XeTeXLayoutEngine engine, int reqFirst) +{ + if (reqFirst) + return engine->font->getFirstCharCode(); + else + return engine->font->getLastCharCode(); +} + +const char* +getGlyphName(XeTeXFont font, UInt16 gid, int* len) +{ + return ((XeTeXFontInst*)font)->getGlyphName(gid, *len); +} + int 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 diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h index cc4d2d8a8de..d92cca16d91 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h @@ -84,7 +84,7 @@ float getGlyphWidth(XeTeXFont font, UInt32 gid); UInt32 countGlyphs(XeTeXFont font); XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, UInt32 scriptTag, UInt32 languageTag, - UInt32* addFeatures, UInt32* removeFeatures, UInt32 rgbValue); + UInt32* addFeatures, SInt32* addParams, UInt32* removeFeatures, UInt32 rgbValue); void deleteLayoutEngine(XeTeXLayoutEngine engine); @@ -132,6 +132,10 @@ int mapGlyphToIndex(XeTeXLayoutEngine engine, const char* glyphName); int findGlyphInPostTable(const char* p, int tableSize, const char* glyphName); +const char* getGlyphName(XeTeXFont font, UInt16 gid, int* len); + +int getFontCharRange(XeTeXLayoutEngine engine, int reqFirst); + #ifdef __cplusplus }; #endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp index 8eedae283ce..d8ef3ed3a04 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp @@ -57,7 +57,8 @@ static le_int32 getLanguageCode(LETag languageTag) LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory (const XeTeXFontInst* fontInstance, LETag scriptTag, LETag languageTag, - const LETag* addFeatures, const LETag* removeFeatures, + const LETag* addFeatures, const le_int32* addParams, + const LETag* removeFeatures, LEErrorCode &success) { static le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG; @@ -101,7 +102,7 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory case hiraScriptCode: case kanaScriptCode: case hrktScriptCode: - result = new XeTeXHanLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, removeFeatures); + result = new XeTeXHanLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, addParams, removeFeatures); break; case khmrScriptCode: @@ -109,7 +110,7 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory break; default: - result = new XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, removeFeatures); + result = new XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, addFeatures, addParams, removeFeatures); break; } } @@ -157,7 +158,7 @@ const char XeTeXOTLayoutEngine::fgClassID=0; XeTeXOTLayoutEngine::XeTeXOTLayoutEngine( const LEFontInstance* fontInstance, LETag scriptTag, LETag languageTag, const GlyphSubstitutionTableHeader* gsubTable, - const LETag* addFeatures, const LETag* removeFeatures) + 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; @@ -177,16 +178,18 @@ XeTeXOTLayoutEngine::XeTeXOTLayoutEngine( } } - adjustFeatures(addFeatures, removeFeatures); + adjustFeatures(addFeatures, addParams, removeFeatures); } XeTeXOTLayoutEngine::~XeTeXOTLayoutEngine() { if (fFeatureList != NULL && fFeatureList != fDefaultFeatures) LE_DELETE_ARRAY(fFeatureList); + if (fFeatureParamList != NULL) + LE_DELETE_ARRAY(fFeatureParamList); } -void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const LETag* removeTags) +void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const le_int32* addParams, const LETag* removeTags) { // bail out if nothing was requested! if ((addTags == NULL || *addTags == emptyTag) && (removeTags == NULL || *removeTags == emptyTag)) @@ -208,6 +211,8 @@ void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const LETag* remo // 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; @@ -217,13 +222,16 @@ void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const LETag* remo break; else t++; - if (t == NULL || *t == emptyTag) + if (t == NULL || *t == emptyTag) { *dest++ = *pTag; + *dest2++ = 0; + } pTag++; } - // copy the added tags, skipping any already present + // 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; @@ -232,9 +240,12 @@ void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const LETag* remo break; else t++; - if (t == dest) - *dest++ = *pTag; + if (t == dest) { + *dest++ = *pTag; + *dest2++ = *pParam; + } pTag++; + pParam++; } // terminate the new list @@ -245,6 +256,7 @@ void XeTeXOTLayoutEngine::adjustFeatures(const LETag* addTags, const LETag* remo LE_DELETE_ARRAY(fFeatureList); fFeatureList = newList; + fFeatureParamList = newParams; } @@ -265,15 +277,16 @@ static const LETag verticalFeatures[] = {loclFeatureTag, vrt2FeatureTag, vertFea 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) + const LETag *addFeatures, const le_int32* addParams, + const LETag *removeFeatures) + : XeTeXOTLayoutEngine(fontInstance, scriptTag, languageTag, gsubTable, NULL, NULL, NULL) { // reset the default feature list fFeatureList = fontInstance->getLayoutDirVertical() ? verticalFeatures : horizontalFeatures; fDefaultFeatures = fFeatureList; // then apply any adjustments - adjustFeatures(addFeatures, removeFeatures); + adjustFeatures(addFeatures, addParams, removeFeatures); } XeTeXHanLayoutEngine::~XeTeXHanLayoutEngine() diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.h b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.h index 9e29f475963..48f48e58abb 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.h @@ -43,11 +43,12 @@ class XeTeXOTLayoutEngine : public OpenTypeLayoutEngine public: XeTeXOTLayoutEngine(const LEFontInstance* fontInstance, LETag scriptTag, LETag languageTag, const GlyphSubstitutionTableHeader* gsubTable, - const LETag* addFeatures, const LETag* removeFeatures); + const LETag* addFeatures, const le_int32* addParams, + const LETag* removeFeatures); virtual ~XeTeXOTLayoutEngine(); - virtual void adjustFeatures(const LETag* addTags, const LETag* removeTags); + virtual void adjustFeatures(const LETag* addTags, const le_int32* addParams, const LETag* removeTags); virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } @@ -55,7 +56,8 @@ public: static LayoutEngine* LayoutEngineFactory (const XeTeXFontInst* fontInstance, LETag scriptTag, LETag languageTag, - const LETag* addFeatures, const LETag* removeFeatures, + const LETag* addFeatures, const le_int32* addParams, + const LETag* removeFeatures, LEErrorCode &success); protected: @@ -66,57 +68,16 @@ private: }; -class XeTeXArabicLayoutEngine : public ArabicOpenTypeLayoutEngine -{ -public: - XeTeXArabicLayoutEngine(const LEFontInstance *fontInstance, LETag scriptTag, LETag languageTag, - const GlyphSubstitutionTableHeader *gsubTable, - const LETag *addFeatures, const LETag *removeFeatures); - - virtual ~XeTeXArabicLayoutEngine(); - - virtual void adjustFeatures(const LETag* addTags, const LETag* removeTags); - - virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } - static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } - -private: - static const char fgClassID; - - const LETag* fDefaultFeatures; -}; - -class XeTeXIndicLayoutEngine : public IndicOpenTypeLayoutEngine -{ -public: - XeTeXIndicLayoutEngine(const LEFontInstance *fontInstance, LETag scriptTag, LETag languageTag, - const GlyphSubstitutionTableHeader *gsubTable, - const LETag *addFeatures, const LETag *removeFeatures); - - virtual ~XeTeXIndicLayoutEngine(); - - virtual void adjustFeatures(const LETag* addTags, const LETag* removeTags); - - virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } - static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } - -private: - static const char fgClassID; - - const LETag* fDefaultFeatures; -}; - class XeTeXHanLayoutEngine : public XeTeXOTLayoutEngine { public: XeTeXHanLayoutEngine(const XeTeXFontInst *fontInstance, LETag scriptTag, LETag languageTag, const GlyphSubstitutionTableHeader *gsubTable, - const LETag *addFeatures, const LETag *removeFeatures); + const LETag* addFeatures, const le_int32* addParams, + const LETag* removeFeatures); virtual ~XeTeXHanLayoutEngine(); -// virtual void adjustFeatures(const LETag* addTags, const LETag* removeTags); - virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp new file mode 100644 index 00000000000..83f50068384 --- /dev/null +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp @@ -0,0 +1,376 @@ +/****************************************************************************\ + 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 "XeTeX_ext.h" +#include "XeTeXLayoutInterface.h" +#include "XeTeXFontInst.h" +#include "XeTeXOTMath.h" +#include "CoverageTables.h" + +#define kMATHTableTag 0x4D415448 + +typedef void* voidptr; +extern voidptr* fontlayoutengine; +extern integer* fontarea; +extern integer* fontsize; + +#include "LESwaps.h" + +int getMathConstant(LEFontInstance* fontInst, mathConstantIndex whichConstant) +{ + const char* table = (const char*)fontInst->getFontTable(kMATHTableTag); + if (table == NULL) + return 0; + + const UInt16* constants = (const UInt16*)(table + SWAPW(((const MathTableHeader*)table)->mathConstants)); + + if (whichConstant < firstMathValueRecord) { + /* it's a simple 16-bit value */ + return SWAPW(constants[whichConstant]); + } + else if (whichConstant <= lastMathValueRecord) { + const MathValueRecord* valueRecords = (const MathValueRecord*) + ((char*)constants + firstMathValueRecord * sizeof(UInt16) - firstMathValueRecord * sizeof(MathValueRecord)); + return SWAPW(valueRecords[whichConstant].value); + } + else if (whichConstant <= lastMathConstant) { + return SWAPW(constants[whichConstant + (lastMathValueRecord - firstMathValueRecord + 1)]); + } + else + return 0; /* or abort, with "internal error" or something */ +} + +int +getotmathconstant(int f, int n) +{ + int rval = 0; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = X2Fix(getMathConstant(font, (mathConstantIndex)n) * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + return rval; +} + +/* fontdimen IDs for math symbols font (family 2) */ +#define math_x_height 5 +#define math_quad 6 +#define num1 8 /* numerator shift-up in display styles */ +#define num2 9 /* numerator shift-up in non-display, non-\.{\\atop} */ +#define num3 10 /* numerator shift-up in non-display \.{\\atop} */ +#define denom1 11 /* denominator shift-down in display styles */ +#define denom2 12 /* denominator shift-down in non-display styles */ +#define sup1 13 /* superscript shift-up in uncramped display style */ +#define sup2 14 /* superscript shift-up in uncramped non-display */ +#define sup3 15 /* superscript shift-up in cramped styles */ +#define sub1 16 /* subscript shift-down if superscript is absent */ +#define sub2 17 /* subscript shift-down if superscript is present */ +#define sup_drop 18 /* superscript baseline below top of large box */ +#define sub_drop 19 /* subscript baseline below bottom of large box */ +#define delim1 20 /* size of \.{\\atopwithdelims} delimiters */ +#define delim2 21 /* size of \.{\\atopwithdelims} delimiters in non-displays */ +#define axis_height 22 /* height of fraction lines above the baseline */ + +const mathConstantIndex TeX_sym_to_OT_map[] = { + unknown, + unknown, + unknown, + unknown, + unknown, + accentBaseHeight, // x-height + unknown, // quad + unknown, + fractionNumeratorDisplayStyleShiftUp, + fractionNumeratorShiftUp, + stackTopShiftUp, + fractionDenominatorDisplayStyleShiftDown, + fractionDenominatorShiftDown, + superscriptShiftUp, // ?? + superscriptShiftUp, // ?? + superscriptShiftUpCramped, + subscriptShiftDown, // ?? + subscriptShiftDown, // ?? + superscriptBaselineDropMax, // ?? + subscriptBaselineDropMin, // ?? + stackDisplayStyleGapMin, + stackGapMin, + axisHeight +}; + +int +getnativemathsyparam(int f, int n) +{ + int rval = 0; + + if (n == math_quad) + rval = fontsize[f]; + else { + if (n < sizeof(TeX_sym_to_OT_map) / sizeof(mathConstantIndex)) { + mathConstantIndex ot_index = TeX_sym_to_OT_map[n]; + if (ot_index != unknown) + rval = getotmathconstant(f, (int)ot_index); + } + } +// fprintf(stderr, " math_sy(%d, %d) returns %.3f\n", f, n, Fix2X(rval)); + + return rval; +} + +/* fontdimen IDs for math extension font (family 3) */ +#define default_rule_thickness 8 /* thickness of \.{\\over} bars */ +#define big_op_spacing1 9 /* minimum clearance above a displayed op */ +#define big_op_spacing2 10 /* minimum clearance below a displayed op */ +#define big_op_spacing3 11 /* minimum baselineskip above displayed op */ +#define big_op_spacing4 12 /* minimum baselineskip below displayed op */ +#define big_op_spacing5 13 /* padding above and below displayed limits */ + +const mathConstantIndex TeX_ext_to_OT_map[] = { + unknown, + unknown, + unknown, + unknown, + unknown, + accentBaseHeight, // x-height + unknown, // quad + unknown, + fractionRuleThickness, // default_rule_thickness + upperLimitGapMin, // big_op_spacing1 + lowerLimitGapMin, // big_op_spacing2 + upperLimitBaselineRiseMin, // big_op_spacing3 + lowerLimitBaselineDropMin, // big_op_spacing4 + stackGapMin // big_op_spacing5 +}; + +int +getnativemathexparam(int f, int n) +{ + int rval = 0; + + if (n == math_quad) + rval = fontsize[f]; + else { + if (n < sizeof(TeX_ext_to_OT_map) / sizeof(mathConstantIndex)) { + mathConstantIndex ot_index = TeX_ext_to_OT_map[n]; + if (ot_index != unknown) + rval = getotmathconstant(f, (int)ot_index); + } + } +// fprintf(stderr, " math_ex(%d, %d) returns %.3f\n", f, n, Fix2X(rval)); + + return rval; +} + +int +getotmathvariant(int f, int g, int v, int* adv) +{ + int rval = g; + *adv = -1; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = (const char*)font->getFontTable(kMATHTableTag); + if (table == NULL) + return rval; + + le_uint16 offset = SWAPW(((const MathTableHeader*)table)->mathVariants); + if (offset == 0) + return rval; + const MathVariants* variants = (const MathVariants*)(table + offset); + + offset = SWAPW(variants->vertGlyphCoverage); + if (offset == 0) + return rval; + const CoverageTable* coverage = (const CoverageTable*)(((const char*)variants) + offset); + + le_int32 index = coverage->getGlyphCoverage(g); + if (index >= 0) { + const MathGlyphConstruction* construction = (const MathGlyphConstruction*)(((const char*)variants) + + SWAPW(variants->vertGlyphConstruction[index])); + if (v < SWAPW(construction->variantCount)) { + rval = SWAPW(construction->mathGlyphVariantRecord[v].variantGlyph); + *adv = X2Fix(SWAPW(construction->mathGlyphVariantRecord[v].advanceMeasurement) + * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + } + } + + return rval; +} + +void* +getotassemblyptr(int f, int g) +{ + void* rval = NULL; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = (const char*)font->getFontTable(kMATHTableTag); + if (table == NULL) + return rval; + + le_uint16 offset = SWAPW(((const MathTableHeader*)table)->mathVariants); + if (offset == 0) + return rval; + const MathVariants* variants = (const MathVariants*)(table + offset); + + offset = SWAPW(variants->vertGlyphCoverage); + if (offset == 0) + return rval; + const CoverageTable* coverage = (const CoverageTable*)(((const char*)variants) + offset); + + le_int32 index = coverage->getGlyphCoverage(g); + if (index >= 0) { + const MathGlyphConstruction* construction = (const MathGlyphConstruction*)(((const char*)variants) + + SWAPW(variants->vertGlyphConstruction[index])); + offset = SWAPW(construction->glyphAssembly); + if (offset != 0) + rval = (void*)(((const char*)construction) + offset); + } + } + + return rval; +} + +int +getotmathitalcorr(int f, int g) +{ + int rval = 0; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = (const char*)font->getFontTable(kMATHTableTag); + if (table == NULL) + return rval; + + le_uint16 offset = SWAPW(((const MathTableHeader*)table)->mathGlyphInfo); + if (offset == 0) + return rval; + const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); + + offset = SWAPW(glyphInfo->mathItalicsCorrectionInfo); + if (offset == 0) + return rval; + const MathItalicsCorrectionInfo* italCorrInfo = (const MathItalicsCorrectionInfo*)(((const char*)glyphInfo) + offset); + + offset = SWAPW(italCorrInfo->coverage); + if (offset == 0) + return rval; + const CoverageTable* coverage = (const CoverageTable*)(((const char*)italCorrInfo) + offset); + + le_int32 index = coverage->getGlyphCoverage(g); + if (index >= 0 && index < SWAPW(italCorrInfo->italicsCorrectionCount)) + rval = X2Fix(SWAPW(italCorrInfo->italicsCorrection[index].value) * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + + return rval; +} + +int +otminconnectoroverlap(int f) +{ + int rval = 0; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = (const char*)font->getFontTable(kMATHTableTag); + if (table == NULL) + return rval; + + le_uint16 offset = SWAPW(((const MathTableHeader*)table)->mathVariants); + if (offset == 0) + return rval; + const MathVariants* variants = (const MathVariants*)(table + offset); + + rval = X2Fix(SWAPW(variants->minConnectorOverlap) * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + + return rval; +} + +int +otpartcount(const GlyphAssembly* a) +{ + return SWAPW(a->partCount); +} + +int +otpartglyph(const GlyphAssembly* a, int i) +{ + return SWAPW(a->partRecords[i].glyph); +} + +int +otpartisextender(const GlyphAssembly* a, int i) +{ + return (SWAPW(a->partRecords[i].partFlags) & fExtender) != 0; +} + +int +otpartstartconnector(int f, const GlyphAssembly* a, int i) +{ + int rval = 0; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = X2Fix(SWAPW(a->partRecords[i].startConnectorLength) * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + + return rval; +} + +int +otpartendconnector(int f, const GlyphAssembly* a, int i) +{ + int rval = 0; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = X2Fix(SWAPW(a->partRecords[i].endConnectorLength) * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + + return rval; +} + +int +otpartfulladvance(int f, const GlyphAssembly* a, int i) +{ + int rval = 0; + + if (fontarea[f] == OT_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = X2Fix(SWAPW(a->partRecords[i].fullAdvance) * Fix2X(fontsize[f]) / font->getUnitsPerEM()); + } + + return rval; +} diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h new file mode 100644 index 00000000000..a1d535923ef --- /dev/null +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h @@ -0,0 +1,62 @@ +/****************************************************************************\ + 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. +\****************************************************************************/ + +#ifndef __XETEX_OT_MATH__ +#define __XETEX_OT_MATH__ + +#include "MathTable.h" + +#include "LEFontInstance.h" + +/* public "C" APIs for calling from Web(-to-C) code */ +extern "C" { + int getnativemathsyparam(int f, int n); + int getnativemathexparam(int f, int n); + int getotmathconstant(int f, int n); + int getotmathvariant(int f, int g, int v, int* adv); + void* getotassemblyptr(int f, int g); + int getotmathitalcorr(int f, int g); + int otpartcount(const GlyphAssembly* a); + int otpartglyph(const GlyphAssembly* a, int i); + int otpartisextender(const GlyphAssembly* a, int i); + int otpartstartconnector(int f, const GlyphAssembly* a, int i); + int otpartendconnector(int f, const GlyphAssembly* a, int i); + int otpartfulladvance(int f, const GlyphAssembly* a, int i); + int otminconnectoroverlap(int f); +}; + + +/* internal functions */ + +/* get a math font constant, scaled according to the font size */ +int getMathConstant(LEFontInstance* fontInst, mathConstantIndex whichConstant); + + +#endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c index 0a7eb956a6e..aaba6a1d8c7 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c @@ -442,6 +442,37 @@ read_tag(const char* cp) return tag; } +static UInt32 +read_tag_with_param(const char* cp, SInt32* param) +{ + UInt32 tag = 0; + int i; + for (i = 0; i < 4; ++i) { + tag <<= 8; + if (*cp && /* *cp < 128 && */ *cp != ',' && *cp != ';' && *cp != ':') { + tag += *(unsigned char*)cp; + ++cp; + } + else + tag += ' '; + } + if (*cp == '=') { + int neg = 0; + ++cp; + if (*cp == '-') { + ++neg; + ++cp; + } + while (*cp >= '0' && *cp <= '9') { + *param = *param * 10 + *cp - '0'; + ++cp; + } + if (neg) + *param = -(*param); + } + return tag; +} + static void* loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const char* cp1) { @@ -451,6 +482,7 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha UInt32* addFeatures = 0; UInt32* removeFeatures = 0; + SInt32* addParams = 0; int nAdded = 0; int nRemoved = 0; @@ -579,13 +611,19 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha } if (*cp1 == '+') { - tag = read_tag(cp1 + 1); + SInt32 param = 0; + tag = read_tag_with_param(cp1 + 1, ¶m); ++nAdded; - if (nAdded == 1) + if (nAdded == 1) { addFeatures = xmalloc(sizeof(UInt32)); - else + addParams = xmalloc(sizeof(SInt32)); + } + else { addFeatures = xrealloc(addFeatures, nAdded * sizeof(UInt32)); + addParams = xrealloc(addParams, nAdded * sizeof(SInt32)); + } addFeatures[nAdded-1] = tag; + addParams[nAdded-1] = param; goto next_option; } @@ -637,11 +675,14 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha if ((loadedfontflags & FONT_FLAGS_VERTICAL) != 0) setFontLayoutDir(font, 1); - engine = createLayoutEngine(fontRef, font, scriptTag, languageTag, addFeatures, removeFeatures, rgbValue); + engine = createLayoutEngine(fontRef, font, scriptTag, languageTag, + addFeatures, addParams, removeFeatures, rgbValue); if (engine == 0) { deleteFont(font); if (addFeatures) free(addFeatures); + if (addParams) + free(addParams); if (removeFeatures) free(removeFeatures); } @@ -657,8 +698,11 @@ splitFontName(char* name, char** var, char** feat, char** end) *var = NULL; *feat = NULL; if (*name == '[') { - ++name; int withinFileName = 1; +#ifdef WIN32 + char* start = name + 1; +#endif + ++name; while (*name) { if (withinFileName && *name == ']') { withinFileName = 0; @@ -666,7 +710,11 @@ splitFontName(char* name, char** var, char** feat, char** end) *var = name; } else if (*name == ':') { - if (withinFileName && *var == NULL) + if (withinFileName && *var == NULL +#ifdef WIN32 + && !((name - start == 1) && isalpha(*start)) +#endif + ) *var = name; else if (!withinFileName && *feat == NULL) *feat = name; @@ -1347,6 +1395,18 @@ getnativecharwd(int f, int c) return wd; } +UInt16 +get_native_glyph_id(void* pNode, unsigned index) +{ + memoryword* node = (memoryword*)pNode; + FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); + UInt16* glyphIDs = (UInt16*)(locations + native_glyph_count(node)); + if (index >= native_glyph_count(node)) + return 0; + else + return glyphIDs[index]; +} + void store_justified_native_glyphs(void* node) { @@ -1691,6 +1751,22 @@ mapglyphtoindex(int font) } } +int +getfontcharrange(int font, int first) +{ +#ifdef XETEX_MAC + if (fontarea[font] == AAT_FONT_FLAG) + return GetFontCharRange_AAT((ATSUStyle)(fontlayoutengine[font]), first); + else +#endif + if (fontarea[font] == OT_FONT_FLAG) + return getFontCharRange((XeTeXLayoutEngine)(fontlayoutengine[font]), first); + else { + fprintf(stderr, "\n! Internal error: bad native font flag\n"); + exit(3); + } +} + #ifndef XETEX_MAC Fixed X2Fix(double d) { @@ -2072,64 +2148,29 @@ atsuprintfontname(int what, ATSUStyle style, int param1, int param2) #endif } -#ifdef XETEX_OTHER -#if 0 -#include <wand/magick-wand.h> -int -find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) - /* FIXME: not yet handling /page/ parameter or PDFs properly */ +void +printglyphname(int font, int gid) { - int err = -1; - MagickBooleanType status; - MagickWand *wand; - ResolutionType units; - double xRes, yRes; - char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1); - - *path = NULL; - - wand = NewMagickWand(); - status = MagickPingImage(wand, pic_path); - if (status == MagickTrue) { - status = MagickGetImageResolution(wand, &xRes, &yRes); - if (status == MagickTrue) { - bounds->x = bounds->y = 0; - units = MagickGetImageUnits(wand); - switch (units) { - default: - /* treat unknown as 72 pixels per inch horiz, and proportionately vertical */ - bounds->wd = MagickGetImageWidth(wand); - if (xRes != 0.0 && yRes != 0.0) - bounds->ht = MagickGetImageHeight(wand) * xRes / yRes; - else - bounds->ht = MagickGetImageHeight(wand); - break; - case PixelsPerInchResolution: - bounds->wd = MagickGetImageWidth(wand) * 72.0 / xRes; - bounds->ht = MagickGetImageHeight(wand) * 72.0 / yRes; - break; - case PixelsPerCentimeterResolution: - bounds->wd = MagickGetImageWidth(wand) * 72.0 / (xRes * 2.54); - bounds->ht = MagickGetImageHeight(wand) * 72.0 / (yRes * 2.54); - break; - } - err = 0; - } - } - - /* current API returns wand, but formerly returned void; - we don't need the result, and this allows XeTeX to build with older libraries */ - (void)DestroyMagickWand(wand); - - if (err != 0) - free(pic_path); + char* s; + int len = 0; +#ifdef XETEX_MAC + if (fontarea[font] == AAT_FONT_FLAG) { + ATSUStyle style = (ATSUStyle)(fontlayoutengine[font]); + s = GetGlyphName_AAT(style, gid, &len); + } else - *path = pic_path; - - return err; -} -#endif #endif + if (fontarea[font] == OT_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + s = (char*)getGlyphName(getFont(engine), gid, &len); + } + else { + fprintf(stderr, "\n! Internal error: bad native font flag\n"); + exit(3); + } + while (len-- > 0) + printchar(*s++); +} boolean u_open_in(unicodefile* f, int filefmt, const_string fopen_mode, int mode, int encodingData) @@ -2343,8 +2384,9 @@ makeutf16name() } t = nameoffile16; while (s <= nameoffile + namelength) { + UInt16 extraBytes; rval = *(s++); - UInt16 extraBytes = bytesFromUTF8[rval]; + extraBytes = bytesFromUTF8[rval]; switch (extraBytes) { /* note: code falls through cases! */ case 5: rval <<= 6; if (*s) rval += *(s++); case 4: rval <<= 6; if (*s) rval += *(s++); diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h index 5a0bc59db50..3161d2fcfb9 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h @@ -177,7 +177,7 @@ struct postTable { }; #define kPost 0x706f7374 - +#define kCmap 0x636d6170 typedef struct { @@ -249,6 +249,8 @@ extern "C" { int mapchartoglyph(int font, unsigned int ch); int mapglyphtoindex(int font); + const char* getGlyphNamePtr(const char* buffer, int tableSize, UInt16 gid, int* len); + int find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page); #ifdef XETEX_MAC @@ -262,6 +264,8 @@ extern "C" { int MapCharToGlyph_AAT(ATSUStyle style, UInt32 ch); int MapGlyphToIndex_AAT(ATSUStyle style, const char* glyphName); float GetGlyphItalCorr_AAT(ATSUStyle style, UInt16 gid); + char* GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len); + int GetFontCharRange_AAT(ATSUStyle style, int reqFirst); #endif #ifdef __cplusplus }; diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c index 8a892be8fc4..6aba6083f41 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c @@ -43,7 +43,7 @@ authorization from SIL International. #undef input /* this is defined in texmfmp.h, but we don't need it and it confuses the carbon headers */ #include <Carbon/Carbon.h> -#include <Quicktime/Quicktime.h> +#include <QuickTime/QuickTime.h> #include "TECkit_Engine.h" #include "XeTeX_ext.h" @@ -468,6 +468,61 @@ int MapGlyphToIndex_AAT(ATSUStyle style, const char* glyphName) return rval; } +char* +GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len) +{ + static char buffer[256]; + const char* namePtr; + + ATSUFontID fontID; + ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &fontID, 0); + + ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID); + + ByteCount length; + OSStatus status = ATSFontGetTable(fontRef, kPost, 0, 0, 0, &length); + if (status != noErr) + return 0; + + void* table = xmalloc(length); + status = ATSFontGetTable(fontRef, kPost, 0, length, table, &length); + if (status != noErr) { + free(table); + return 0; + } + + namePtr = getGlyphNamePtr(table, length, gid, len); + if (*len > 255) + *len = 255; + if (namePtr) { + memcpy(buffer, namePtr, *len); + buffer[*len] = 0; + } + + free(table); + + return &buffer[0]; +} + +/* +int +GetFontCharRange_AAT(ATSUStyle style, int reqFirst) +{ + 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; + } +} +*/ + ATSUFontVariationAxis find_axis_by_name(ATSUFontID fontID, const char* name, int nameLength) { diff --git a/Build/source/texk/web2c/xetexdir/trans.h b/Build/source/texk/web2c/xetexdir/trans.h index 2a24a60f7ee..a1bb8780fb7 100644 --- a/Build/source/texk/web2c/xetexdir/trans.h +++ b/Build/source/texk/web2c/xetexdir/trans.h @@ -74,13 +74,15 @@ typedef struct { #define bField(t) t.b #define cField(t) t.c #define dField(t) t.d -#ifdef XETEX_MAC -#define xField(t) t.tx -#define yField(t) t.ty +#ifdef XETEX_MAC /* transform fields have different names */ +#define txField(t) t.tx +#define tyField(t) t.ty #else +#define txField(t) t.x +#define tyField(t) t.y +#endif #define xField(t) t.x #define yField(t) t.y -#endif #define setPoint(P,X,Y) do { P.x = X; P.y = Y; } while (0) diff --git a/Build/source/texk/web2c/xetexdir/unicode-char-prep.pl b/Build/source/texk/web2c/xetexdir/unicode-char-prep.pl index 31b27de7dc9..8dd2581edcc 100644 --- a/Build/source/texk/web2c/xetexdir/unicode-char-prep.pl +++ b/Build/source/texk/web2c/xetexdir/unicode-char-prep.pl @@ -80,7 +80,7 @@ print << '__EOT__'; \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \def\C #1 #2 #3 {\global\uccode"#1="#2 \global\lccode"#1="#3 } % case mappings (non-letter) \def\L #1 #2 #3 {\global\catcode"#1=11 \C #1 #2 #3 % letter with case mappings - \global\XeTeXextmathcode"#1="7"01"#1 } % letters default to class 7 (var), fam 1 + \global\XeTeXmathcode"#1="7"01"#1 } % letters default to class 7 (var), fam 1 \def\l #1 {\L #1 #1 #1 } % letter without case mappings \let\m=\l % combining mark - treated as uncased letter __EOT__ diff --git a/Build/source/texk/web2c/xetexdir/xetex-new.ch b/Build/source/texk/web2c/xetexdir/xetex-new.ch index 7f76fbdcd6b..66cc3f57c14 100644 --- a/Build/source/texk/web2c/xetexdir/xetex-new.ch +++ b/Build/source/texk/web2c/xetexdir/xetex-new.ch @@ -55,8 +55,8 @@ @d eTeX_version_string=='-2.2' {current \eTeX\ version} @d XeTeX_version=0 -@d XeTeX_revision==".995" -@d XeTeX_version_string=='-0.995' {current \eTeX\ version} +@d XeTeX_revision==".996" +@d XeTeX_version_string=='-0.996' {current \XeTeX\ version} @z @x @@ -1164,14 +1164,6 @@ else begin print_esc("scriptscriptfont"); @d saving_hyph_codes==int_par(saving_hyph_codes_code) @d XeTeX_linebreak_locale==int_par(XeTeX_linebreak_locale_code) @d XeTeX_linebreak_penalty==int_par(XeTeX_linebreak_penalty_code) - -@ @<Global...@>= -xetex_del_code_base:integer; { a hack, because WEB defined constants don't make it through to C } - -@ @<Set init...@>= -xetex_del_code_base:=del_code_base; - -@ New sections slipped in above here. @z @x @@ -1197,7 +1189,6 @@ del_code("."):=0; {this null delimiter is used in error recovery} @y for k:=0 to number_chars-1 do del_code(k):=-1; del_code("."):=0; {this null delimiter is used in error recovery} -set_del_code1(".",0); @z @x @@ -1295,6 +1286,13 @@ else begin k:=str_start_macro(s); l:=str_start_macro(s+1)-k; @z @x +primitive("delimiter",delim_num,0);@/ +@y +primitive("delimiter",delim_num,0);@/ +primitive("XeTeXdelimiter",delim_num,1);@/ +@z + +@x primitive("mathaccent",math_accent,0);@/ @y primitive("mathaccent",math_accent,0);@/ @@ -1306,18 +1304,32 @@ primitive("mathchar",math_char_num,0);@/ @!@:math_char_}{\.{\\mathchar} primitive@> @y primitive("mathchar",math_char_num,0);@/ -primitive("XeTeXmathchar",math_char_num,1);@/ -primitive("XeTeXextmathchar",math_char_num,2);@/ +primitive("XeTeXmathcharnum",math_char_num,1);@/ +primitive("XeTeXmathchar",math_char_num,2);@/ @!@:math_char_}{\.{\\mathchar} primitive@> @z @x +primitive("radical",radical,0);@/ +@y +primitive("radical",radical,0);@/ +primitive("XeTeXradical",radical,1);@/ +@z + +@x primitive("relax",relax,256); {cf.\ |scan_file_name|} @y primitive("relax",relax,too_big_char); {cf.\ |scan_file_name|} @z @x +delim_num: print_esc("delimiter"); +@y +delim_num: if chr_code=1 then print_esc("XeTeXdelimiter") + else print_esc("delimiter"); +@z + +@x end_cs_name: if chr_code = 10 then print_esc("endmubyte") else print_esc("endcsname"); @y @@ -1334,20 +1346,27 @@ math_accent: if chr_code=1 then print_esc("XeTeXmathaccent") @x math_char_num: print_esc("mathchar"); @y -math_char_num: if chr_code=2 then print_esc("XeTeXextmathchar") - else if chr_code=1 then print_esc("XeTeXmathchar") +math_char_num: if chr_code=2 then print_esc("XeTeXmathchar") + else if chr_code=1 then print_esc("XeTeXmathcharnum") else print_esc("mathchar"); @z @x +radical: print_esc("radical"); +@y +radical: if chr_code=1 then print_esc("XeTeXradical") else print_esc("radical"); +@z + +@x @* \[19] Saving and restoring equivalents. @y @* \[19] Saving and restoring equivalents. @z -@x +-- based on Omega; not needed with new xetex delimiter coding + x @ The |eq_define| and |eq_word_define| routines take care of local definitions. -@y + y @# procedure eq_word_define1(@!p:pointer;@!w:integer); label exit; @@ -1364,11 +1383,11 @@ assign_trace(p,"into")@;@/ exit:end; @ The |eq_define| and |eq_word_define| routines take care of local definitions. -@z + z -@x + x @ Subroutine |save_for_after| puts a token on the stack for save-keeping. -@y + y @# procedure geq_word_define1(@!p:pointer;@!w:integer); {global |eq_word_define1|} begin assign_trace(p,"globally changing")@;@/ @@ -1378,7 +1397,7 @@ assign_trace(p,"into")@;@/ end; @ Subroutine |save_for_after| puts a token on the stack for save-keeping. -@z + z @x @* \[20] Token lists. @@ -1724,17 +1743,21 @@ XeTeX_def_code: begin scan_char_num; if m=math_code_base then begin - cur_val1:=ho(math_code(cur_val)); - scanned_result(cur_val1)(int_val) + scanned_result(ho(math_code(cur_val)))(int_val) end else if m=math_code_base+1 then begin - print_err("Can't use \XeTeXextmathcode as a number"); - help2("\XeTeXextmathcode is for setting a mathcode from separate values;")@/ - ("use \XeTeXmathcode to access them as single values."); error; + print_err("Can't use \XeTeXmathcode as a number"); + help2("\XeTeXmathcode is for setting a mathcode from separate values;")@/ + ("use \XeTeXmathcodenum to access them as single values."); error; scanned_result(0)(int_val) end - else begin - scanned_result(-1)(int_val); { FIXME - XeTeXdelcode } + else if m=del_code_base then begin + scanned_result(ho(del_code(cur_val)))(int_val) + end else begin + print_err("Can't use \XeTeXdelcode as a number"); + help2("\XeTeXdelcode is for setting a delcode from separate values;")@/ + ("use \XeTeXdelcodenum to access them as single values."); error; + scanned_result(0)(int_val); end; end; @z @@ -1749,7 +1772,7 @@ if m=math_code_base then begin cur_val1:=ho(math_code(cur_val)); if is_active_math_char(cur_val1) then cur_val1:=@"8000 - else if (math_class_field(cur_val1)>8) or + else if (math_class_field(cur_val1)>7) or (math_fam_field(cur_val1)>15) or (math_char_field(cur_val1)>255) then begin print_err("Extended mathchar used as mathchar"); @@ -1764,30 +1787,14 @@ if m=math_code_base then begin end else if m=del_code_base then begin cur_val1:=del_code(cur_val); - if (math_class_field(cur_val1) > 8) or - (math_fam_field(cur_val1) > 15) or - (math_char_field(cur_val1) > 255) then begin + if cur_val1>=@"40000000 then begin print_err("Extended delcode used as delcode"); @.Bad delcode@> help2("A delimiter code must be between 0 and ""7FFFFFF.")@/ ("I changed this one to zero."); error; scanned_result(0)(int_val); end else begin - cur_val1:=del_code1(cur_val); - if (math_class_field(cur_val1) > 0) or - (math_fam_field(cur_val1) > 15) or - (math_char_field(cur_val1) > 255) then begin - print_err("Extended delcode used as delcode"); - help2("A delimiter code must be between 0 and ""7FFFFFF.")@/ - ("I changed this one to zero."); error; - scanned_result(0)(int_val); - end else begin - scanned_result(((math_class_field(del_code(cur_val))*@"1000) + - (math_fam_field(del_code(cur_val))*@"100) + - math_char_field(del_code(cur_val)))*@"1000 + - (math_fam_field(cur_val1)*@"100) + - math_char_field(cur_val1))(int_val); - end + scanned_result(cur_val1)(int_val); end end @z @@ -1798,7 +1805,7 @@ end @# @d XeTeX_int=eTeX_int+8 {first of \XeTeX\ codes for integers} @# -@d eTeX_dim=XeTeX_int+27 {first of \eTeX\ codes for dimensions} +@d eTeX_dim=XeTeX_int+29 {first of \eTeX\ codes for dimensions} {changed for \XeTeX\ to make room for \XeTeX\ integers} @z @@ -1886,41 +1893,6 @@ end; procedure scan_four_bit_int; @z - x -procedure scan_fifteen_bit_int; -begin scan_int; -if (cur_val<0)or(cur_val>@'77777) then - begin print_err("Bad mathchar"); -@.Bad mathchar@> - help2("A mathchar number must be between 0 and 32767.")@/ - ("I changed this one to zero."); int_error(cur_val); cur_val:=0; - end; -end; - y -procedure scan_real_fifteen_bit_int; -begin scan_int; -if (cur_val<0)or(cur_val>@'77777) then - begin print_err("Bad mathchar"); -@.Bad mathchar@> - help2("A mathchar number must be between 0 and 32767.")@/ - ("I changed this one to zero."); int_error(cur_val); cur_val:=0; - end; -end; - -procedure scan_fifteen_bit_int; { scans a \mathchar value and expands it to 32-bit form } -begin scan_int; -if (cur_val<0)or(cur_val>@'77777) then - begin print_err("Bad mathchar"); -@.Bad mathchar@> - help2("A mathchar number must be between 0 and 32767.")@/ - ("I changed this one to zero."); int_error(cur_val); cur_val:=0; - end; -cur_val := set_class_field(cur_val div @"1000) + - set_family_field((cur_val mod @"1000) div @"100) + - (cur_val mod @"100); -end; - z - @x procedure scan_twenty_seven_bit_int; begin scan_int; @@ -1940,32 +1912,9 @@ if (cur_val<0)or(cur_val>@'777777777) then help2("A numeric delimiter code must be between 0 and 2^{27}-1.")@/ ("I changed this one to zero."); int_error(cur_val); cur_val:=0; end; -cur_val1 := set_family_field((cur_val mod @"1000) div @"100) + - (cur_val mod @"100); -cur_val := cur_val div @"1000; -cur_val := set_family_field((cur_val mod @"1000) div @"100) + - set_class_field(cur_val div @"1000) + - (cur_val mod @"100); end; @z -procedure scan_twenty_seven_bit_int; -begin scan_int; -if (cur_val<0)or(cur_val>@'777777777) then - begin print_err("Bad delimiter code"); -@.Bad delimiter code@> - help2("A numeric delimiter code must be between 0 and 2^{27}-1.")@/ - ("I changed this one to zero."); int_error(cur_val); cur_val:=0; - end; -cur_val1 := (((cur_val mod @"1000) div @"100) * @"10000) + - (cur_val mod @"100); -cur_val := cur_val div @"1000; -cur_val := ((cur_val div @"1000) * @"1000000) + - (((cur_val mod @"1000) div @"100) * @"10000) + - (cur_val mod @"100); -end; - z - @x if cur_val>255 then @y @@ -2025,8 +1974,9 @@ end; @d XeTeX_variation_name_code=7 { must match codes in xetexmac.c } @d XeTeX_feature_name_code=8 @d XeTeX_selector_name_code=9 +@d XeTeX_glyph_name_code=10 -@d etex_convert_codes=XeTeX_selector_name_code+1 {end of \eTeX's command codes} +@d etex_convert_codes=XeTeX_glyph_name_code+1 {end of \eTeX's command codes} @z @x @@ -4117,11 +4067,11 @@ math_char_num: begin scan_fifteen_bit_int; c:=cur_val; end; @y math_char_num: - if cur_chr = 2 then begin { \XeTeXextmathchar } + if cur_chr = 2 then begin { \XeTeXmathchar } scan_math_class_int; c := set_class_field(cur_val); scan_math_fam_int; c := c + set_family_field(cur_val); scan_usv_num; c := c + cur_val; - end else if cur_chr = 1 then begin { \XeTeXmathchar } + end else if cur_chr = 1 then begin { \XeTeXmathcharnum } scan_xetex_math_char_int; c := cur_val; end else begin scan_fifteen_bit_int; c := set_class_field(cur_val div @"1000) + @@ -4141,8 +4091,17 @@ math_given: begin end; XeTeX_math_given: c:=cur_chr; delim_num: begin - scan_delimiter_int; - c := cur_val; {cur_val is the 'small' delimiter mathchar value} + if cur_chr=1 then begin {\XeTeXdelimiter <cls> <fam> <usv>} + scan_math_class_int; c := set_class_field(cur_val); + scan_math_fam_int; c := c + set_family_field(cur_val); + scan_usv_num; c := c + cur_val; + end else begin {\delimiter <27-bit delcode>} + scan_delimiter_int; + c := cur_val div @'10000; {get the 'small' delimiter field} + c := set_class_field(c div @"1000) + + set_family_field((c mod @"1000) div @"100) + + (c mod @"100); {and convert it to a xetex mathchar code} + end; @z @x @@ -4160,12 +4119,12 @@ plane_and_fam_field(p) := plane_and_fam_field(p) + (math_char_field(c) div @"100 mmode+math_char_num: begin scan_fifteen_bit_int; set_math_char(cur_val); end; @y -mmode+math_char_num: if cur_chr = 2 then begin { \XeTeXextmathchar } +mmode+math_char_num: if cur_chr = 2 then begin { \XeTeXmathchar } scan_math_class_int; t := set_class_field(cur_val); scan_math_fam_int; t := t + set_family_field(cur_val); scan_usv_num; t := t + cur_val; set_math_char(t); - end else if cur_chr = 1 then begin { \XeTeXmathchar } + end else if cur_chr = 1 then begin { \XeTeXmathcharnum } scan_xetex_math_char_int; set_math_char(cur_val); end else begin scan_fifteen_bit_int; set_math_char(set_class_field(cur_val div @"1000) + @@ -4186,8 +4145,18 @@ mmode+math_given: begin end; mmode+XeTeX_math_given: set_math_char(cur_chr); mmode+delim_num: begin - scan_delimiter_int; - set_math_char(cur_val); + if cur_chr=1 then begin {\XeTeXdelimiter} + scan_math_class_int; t := set_class_field(cur_val); + scan_math_fam_int; t := t + set_family_field(cur_val); + scan_usv_num; t := t + cur_val; + set_math_char(t); + end else begin + scan_delimiter_int; + cur_val:=cur_val div @'10000; {discard the large delimiter code} + set_math_char(set_class_field(cur_val div @"1000) + + set_family_field((cur_val mod @"1000) div @"100) + + (cur_val mod @"100)); + end; @z @x @@ -4226,7 +4195,15 @@ procedure scan_delimiter(@!p:pointer;@!r:boolean); begin if r then scan_twenty_seven_bit_int @y procedure scan_delimiter(@!p:pointer;@!r:boolean); -begin if r then scan_delimiter_int +begin + if r then begin + if cur_chr=1 then begin {\XeTeXradical} + cur_val1 := @"40000000; {extended delcode flag} + scan_math_fam_int; cur_val1 := cur_val1 + cur_val * @"200000; + scan_usv_num; cur_val := cur_val1 + cur_val; + end else {\radical} + scan_delimiter_int; + end @z @x @@ -4235,10 +4212,15 @@ begin if r then scan_delimiter_int othercases cur_val:=-1 @y letter,other_char: begin - cur_val:=del_code(cur_chr); cur_val1:=del_code1(cur_chr); + cur_val:=del_code(cur_chr); end; - delim_num: scan_delimiter_int; - othercases begin cur_val:=-1; cur_val1:=-1; end; + delim_num: if cur_chr=1 then begin {\XeTeXdelimiter} + cur_val1 := @"40000000; {extended delcode flag} + scan_math_class_int; {discarded} + scan_math_fam_int; cur_val1 := cur_val1 + cur_val * @"200000; + scan_usv_num; cur_val := cur_val1 + cur_val; + end else scan_delimiter_int; {normal \delimiter} + othercases begin cur_val:=-1; end; @z @x @@ -4251,12 +4233,19 @@ large_char(p):=qi(cur_val mod 256); @y if cur_val<0 then begin @<Report that an invalid delimiter code is being changed to null; set~|cur_val:=0|@>; - cur_val1:=0; end; -small_plane_and_fam_field(p) := (math_char_field(cur_val) div @"10000) * @"100 + math_fam_field(cur_val); -small_char_field(p) := cur_val mod @"10000; -large_plane_and_fam_field(p) := (math_char_field(cur_val1) div @"10000) * @"100 + math_fam_field(cur_val1); -large_char_field(p) := cur_val1 mod @"10000; +if cur_val>=@"40000000 then begin {extended delcode, only one size} + small_plane_and_fam_field(p) := ((cur_val mod @"200000) div @"10000) * @"100 {plane} + + (cur_val div @"200000) mod @"100; {family} + small_char_field(p) := qi(cur_val mod @"10000); + large_plane_and_fam_field(p) := 0; + large_char_field(p) := 0; +end else begin {standard delcode, 4-bit families and 8-bit char codes} + small_plane_and_fam_field(p) := (cur_val div @'4000000) mod 16; + small_char_field(p) := qi((cur_val div @'10000) mod 256); + large_plane_and_fam_field(p) := (cur_val div 256) mod 16; + large_char_field(p) := qi(cur_val mod 256); +end; @z @x @@ -4328,8 +4317,8 @@ any_mode(XeTeX_def_code), @d mu_skip_def_code=5 {|shorthand_def| for \.{\\muskipdef}} @d toks_def_code=6 {|shorthand_def| for \.{\\toksdef}} @d char_sub_def_code=7 {|shorthand_def| for \.{\\charsubdef}} -@d XeTeX_math_char_def_code=8 -@d XeTeX_ext_math_char_def_code=9 +@d XeTeX_math_char_num_def_code=8 +@d XeTeX_math_char_def_code=9 @z @x @@ -4337,8 +4326,8 @@ primitive("mathchardef",shorthand_def,math_char_def_code);@/ @!@:math_char_def_}{\.{\\mathchardef} primitive@> @y primitive("mathchardef",shorthand_def,math_char_def_code);@/ +primitive("XeTeXmathcharnumdef",shorthand_def,XeTeX_math_char_num_def_code);@/ primitive("XeTeXmathchardef",shorthand_def,XeTeX_math_char_def_code);@/ -primitive("XeTeXextmathchardef",shorthand_def,XeTeX_ext_math_char_def_code);@/ @!@:math_char_def_}{\.{\\mathchardef} primitive@> @z @@ -4347,7 +4336,7 @@ primitive("XeTeXextmathchardef",shorthand_def,XeTeX_ext_math_char_def_code);@/ @y math_char_def_code: print_esc("mathchardef"); XeTeX_math_char_def_code: print_esc("XeTeXmathchardef"); - XeTeX_ext_math_char_def_code: print_esc("XeTeXextmathchardef"); + XeTeX_math_char_num_def_code: print_esc("XeTeXmathcharnumdef"); @z @x @@ -4378,10 +4367,10 @@ else begin n:=cur_chr; get_r_token; p:=cur_cs; define(p,relax,too_big_char); @y math_char_def_code: begin scan_fifteen_bit_int; define(p,math_given,cur_val); end; - XeTeX_math_char_def_code: begin scan_xetex_math_char_int; + XeTeX_math_char_num_def_code: begin scan_xetex_math_char_int; define(p, XeTeX_math_given, cur_val); end; - XeTeX_ext_math_char_def_code: begin + XeTeX_math_char_def_code: begin scan_math_class_int; n := set_class_field(cur_val); scan_math_fam_int; n := n + set_family_field(cur_val); scan_usv_num; n := n + cur_val; @@ -4393,15 +4382,24 @@ else begin n:=cur_chr; get_r_token; p:=cur_cs; define(p,relax,too_big_char); primitive("mathcode",def_code,math_code_base); @y primitive("mathcode",def_code,math_code_base); -primitive("XeTeXmathcode",XeTeX_def_code,math_code_base); -primitive("XeTeXextmathcode",XeTeX_def_code,math_code_base+1); +primitive("XeTeXmathcodenum",XeTeX_def_code,math_code_base); +primitive("XeTeXmathcode",XeTeX_def_code,math_code_base+1); +@z + +@x +primitive("delcode",def_code,del_code_base); +@y +primitive("delcode",def_code,del_code_base); +primitive("XeTeXdelcodenum",XeTeX_def_code,del_code_base); +primitive("XeTeXdelcode",XeTeX_def_code,del_code_base+1); @z @x def_family: print_size(chr_code-math_font_base); @y -XeTeX_def_code: if chr_code=math_code_base then print_esc("XeTeXmathcode") - else if chr_code=math_code_base+1 then print_esc("XeTeXextmathcode") +XeTeX_def_code: if chr_code=math_code_base then print_esc("XeTeXmathcodenum") + else if chr_code=math_code_base+1 then print_esc("XeTeXmathcode") + else if chr_code=del_code_base then print_esc("XeTeXdelcodenum") else print_esc("XeTeXdelcode"); def_family: print_size(chr_code-math_font_base); @z @@ -4426,7 +4424,28 @@ XeTeX_def_code: begin scan_usv_num; n := n + cur_val; define(p,data,hi(n)); end - else do_nothing; {FIXME - XeTeXdelcode} + else if cur_chr = del_code_base then begin + p:=cur_chr; scan_char_num; + p:=p+cur_val; + scan_optional_equals; + scan_int; {scan_xetex_del_code_int; !!FIXME!!} + word_define(p,hi(cur_val)); + end else begin +{ +bit usage in delcode values: +original layout: @"00cffCFF small/LARGE family & char +extended: @"40000000 FLAG + + ff << 21 (mult by @"200000) FAMILY + + 1ccccc (21 bits) USV +} + p:=cur_chr-1; scan_char_num; + p:=p+cur_val; + scan_optional_equals; + n := @"40000000; {extended delcode flag} + scan_math_fam_int; n := n + cur_val * @"200000; + scan_usv_num; n := n + cur_val; + word_define(p,hi(n)); + end; end; def_code: begin @<Let |n| be the largest legal code value, based on |cur_chr|@>; @z @@ -4443,27 +4462,16 @@ def_code: begin @<Let |n| be the largest legal code value, based on |cur_chr|@>; if cur_val=@"8000 then cur_val:=active_math_char else cur_val:=set_class_field(cur_val div @"1000) + set_family_field((cur_val mod @"1000) div @"100) + - (cur_val mod @"100); + (cur_val mod @"100); {!!FIXME!! check how this is used} define(p,data,hi(cur_val)); end @z +-- from Omega; not needed with new xetex delimiter coding x else word_define(p,cur_val); y else begin - cur_val1:=cur_val div @"1000; - cur_val1:=(cur_val1 div @"100)*@"10000 + (cur_val1 mod @"100); - cur_val:=cur_val mod @"1000; - cur_val:=(cur_val div @"100)*@"10000 + (cur_val mod @"100); - word_define(p,cur_val); - word_define1(p,cur_val1); - end; - z -@x - else word_define(p,cur_val); -@y - else begin cur_val1 := cur_val mod @"1000; { large delim code } cur_val1 := set_family_field(cur_val1 div @"100) + cur_val1 mod @"100; cur_val := cur_val div @"1000; @@ -4473,7 +4481,7 @@ def_code: begin @<Let |n| be the largest legal code value, based on |cur_chr|@>; word_define(p, cur_val); word_define1(p, cur_val1); end; -@z + z @x else n:=255 @@ -4881,53 +4889,68 @@ begin native_word_node: begin - { merge with any following word fragments, discarding discretionary breaks } + { merge with any following word fragments in same font, discarding discretionary breaks } while (link(q) <> p) do q := link(q); { bring q up in preparation for deletion of nodes starting at p } pp := link(p); restart: - if (pp <> null) and (not is_char_node(pp)) and (type(pp) = disc_node) then begin - ppp := link(pp); - if (ppp <> null) and (not is_char_node(ppp)) and (type(ppp) = whatsit_node) and (subtype(ppp) = native_word_node) and (native_font(ppp) = native_font(p)) then begin - pp := link(ppp); + if (pp <> null) and (not is_char_node(pp)) then begin + if (type(pp) = whatsit_node) + and (subtype(pp) = native_word_node) + and (native_font(pp) = native_font(p)) then begin + pp := link(pp); goto restart; end + else if (type(pp) = disc_node) then begin + ppp := link(pp); + if (ppp <> null) and (not is_char_node(ppp)) + and (type(ppp) = whatsit_node) + and (subtype(ppp) = native_word_node) + and (native_font(ppp) = native_font(p)) then begin + pp := link(ppp); + goto restart; + end + end end; + { now pp points to the non-native_word node that ended the chain, or null } - + + { we can just check type(p)=whatsit_node below, as we know that the chain + contains only discretionaries and native_word nodes, no other whatsits or char_nodes } + if (pp <> link(p)) then begin { found a chain of at least two pieces starting at p } total_chars := 0; - p := q; + p := link(q); { the first fragment } while (p <> pp) do begin - p := link(p); { point to fragment } - total_chars := total_chars + native_length(p); { accumulate char count } - ppp := p; { remember last fragment seen } - p := link(p); { point to discretionary or other terminator } + if (type(p) = whatsit_node) then + total_chars := total_chars + native_length(p); { accumulate char count } + ppp := p; { remember last node seen } + p := link(p); { point to next fragment or discretionary or terminator } end; - - p := link(q); { the first fragment } + + p := link(q); { the first fragment again } pp := new_native_word_node(native_font(p), total_chars); { make new node for merged word } link(q) := pp; { link to preceding material } link(pp) := link(ppp); { attach remainder of hlist to it } link(ppp) := null; { and detach from the old fragments } - + { copy the chars into new node } total_chars := 0; ppp := p; repeat - for k := 0 to native_length(ppp)-1 do begin - set_native_char(pp, total_chars, get_native_char(ppp, k)); - incr(total_chars); - end; + if (type(ppp) = whatsit_node) then + for k := 0 to native_length(ppp)-1 do begin + set_native_char(pp, total_chars, get_native_char(ppp, k)); + incr(total_chars); + end; ppp := link(ppp); - if (ppp <> null) then ppp := link(ppp); { pass a disc_node } until (ppp = null); - + flush_node_list(p); { delete the fragments } p := link(q); { update p to point to the new node } set_native_metrics(p, XeTeX_use_glyph_metrics); { and measure it (i.e., re-do the OT layout) } end; - + { now incorporate the native_word node measurements into the box we're packing } if height(p) > h then h := height(p); @@ -4935,7 +4958,7 @@ begin d := depth(p); x := x + width(p); end; - + glyph_node, pic_node, pdf_node: begin if height(p) > h then @@ -4944,7 +4967,7 @@ begin d := depth(p); x := x + width(p); end; - + othercases do_nothing @@ -5244,12 +5267,7 @@ begin native_font(tail):=cur_font; native_glyph(tail):=cur_val; set_native_glyph_metrics(tail, XeTeX_use_glyph_metrics); - end else begin - print_err("Invalid use of \XeTeXglyph"); - help2("The \XeTeXglyph command can only be used with AAT or OT fonts,") - ("not TFM-based fonts. So I'm ignoring this."); - error; - end + end else not_native_font_error(extension, glyph_code, cur_font); end end @@ -5327,10 +5345,10 @@ begin { access the picture file and check its size } result := find_pic_file(address_of(pic_path), address_of(bounds), pdf_box_type, page); - setPoint(corners[0], 0.0, 0.0); - setPoint(corners[1], 0.0, htField(bounds) * 72.27 / 72.0); - setPoint(corners[2], wdField(bounds) * 72.27 / 72.0, htField(bounds) * 72.27 / 72.0); - setPoint(corners[3], wdField(bounds) * 72.27 / 72.0, 0.0); + setPoint(corners[0], xField(bounds) * 72.27 / 72.0, yField(bounds) * 72.27 / 72.0); + setPoint(corners[1], xField(corners[0]), (yField(bounds) + htField(bounds)) * 72.27 / 72.0); + setPoint(corners[2], (xField(bounds) + wdField(bounds)) * 72.27 / 72.0, yField(corners[1])); + setPoint(corners[3], xField(corners[2]), yField(corners[0])); x_size_req := 0.0; y_size_req := 0.0; @@ -5424,8 +5442,8 @@ begin pic_transform2(tail) := X2Fix(bField(t)); pic_transform3(tail) := X2Fix(cField(t)); pic_transform4(tail) := X2Fix(dField(t)); - pic_transform5(tail) := X2Fix(xField(t)); - pic_transform6(tail) := X2Fix(yField(t)); + pic_transform5(tail) := X2Fix(txField(t)); + pic_transform6(tail) := X2Fix(tyField(t)); memcpy(address_of(mem[tail + pic_node_size]), pic_path, strlen(pic_path)); libc_free(pic_path); @@ -5529,9 +5547,13 @@ end @d XeTeX_glyph_index_code=XeTeX_int+23 @d XeTeX_font_type_code=XeTeX_int+24 -@d pdf_last_x_pos_code = XeTeX_int+25 -@d pdf_last_y_pos_code = XeTeX_int+26 -{ remember to update eTeX_dim when new items are added here } +@d XeTeX_first_char_code=XeTeX_int+25 +@d XeTeX_last_char_code=XeTeX_int+26 + +@d pdf_last_x_pos_code = XeTeX_int+27 +@d pdf_last_y_pos_code = XeTeX_int+28 + +{ NB: must update eTeX_dim when items are added here! } @z @x @@ -5576,8 +5598,13 @@ primitive("XeTeXOTfeaturetag",last_item,XeTeX_OT_feature_code); primitive("XeTeXcharglyph", last_item, XeTeX_map_char_to_glyph_code); primitive("XeTeXglyphindex", last_item, XeTeX_glyph_index_code); +primitive("XeTeXglyphname",convert,XeTeX_glyph_name_code); + primitive("XeTeXfonttype", last_item, XeTeX_font_type_code); +primitive("XeTeXfirstfontchar", last_item, XeTeX_first_char_code); +primitive("XeTeXlastfontchar", last_item, XeTeX_last_char_code); + primitive("pdflastxpos",last_item,pdf_last_x_pos_code); primitive("pdflastypos",last_item,pdf_last_y_pos_code); @z @@ -5618,6 +5645,9 @@ XeTeX_glyph_index_code: print_esc("XeTeXglyphindex"); XeTeX_font_type_code: print_esc("XeTeXfonttype"); +XeTeX_first_char_code: print_esc("XeTeXfirstfontchar"); +XeTeX_last_char_code: print_esc("XeTeXlastfontchar"); + pdf_last_x_pos_code: print_esc("pdflastxpos"); pdf_last_y_pos_code: print_esc("pdflastypos"); @z @@ -5779,6 +5809,17 @@ XeTeX_font_type_code: end end; +XeTeX_first_char_code,XeTeX_last_char_code: + begin + scan_font_ident; n:=cur_val; + if is_native_font(n) then + cur_val:=get_font_char_range(n, m = XeTeX_first_char_code) + else begin + if m = XeTeX_first_char_code then cur_val:=font_bc[n] + else cur_val:=font_ec[n]; + end + end; + pdf_last_x_pos_code: cur_val := pdf_last_x_pos; pdf_last_y_pos_code: cur_val := pdf_last_y_pos; @@ -5825,6 +5866,7 @@ XeTeX_revision_code: print_esc("XeTeXrevision"); XeTeX_variation_name_code: print_esc("XeTeXvariationname"); XeTeX_feature_name_code: print_esc("XeTeXfeaturename"); XeTeX_selector_name_code: print_esc("XeTeXselectorname"); +XeTeX_glyph_name_code: print_esc("XeTeXglyphname"); @ @<Cases of `Scan the argument for command |c|'@>= eTeX_revision_code: do_nothing; @@ -5837,7 +5879,7 @@ XeTeX_feature_name_code: if is_atsu_font(fnt) then begin scan_int; arg1:=cur_val; arg2:=0; end else - not_atsu_font_error(convert, c, f); + not_atsu_font_error(convert, c, fnt); end; XeTeX_selector_name_code: @@ -5846,7 +5888,16 @@ XeTeX_selector_name_code: if is_atsu_font(fnt) then begin scan_int; arg1:=cur_val; scan_int; arg2:=cur_val; end else - not_atsu_font_error(convert, c, f); + not_atsu_font_error(convert, c, fnt); + end; + +XeTeX_glyph_name_code: + begin + scan_font_ident; fnt:=cur_val; + if is_native_font(fnt) then begin + scan_int; arg1:=cur_val; + end else + not_native_font_error(convert, c, fnt); end; @ @<Cases of `Print the result of command |c|'@>= @@ -5858,6 +5909,9 @@ XeTeX_feature_name_code, XeTeX_selector_name_code: if is_atsu_font(fnt) then atsu_print_font_name(c, font_layout_engine[fnt], arg1, arg2); + +XeTeX_glyph_name_code: + if is_native_font(fnt) then print_glyph_name(fnt, arg1); @z @x diff --git a/Build/source/texk/web2c/xetexdir/xetex-otmath.ch b/Build/source/texk/web2c/xetexdir/xetex-otmath.ch new file mode 100644 index 00000000000..2df2af6652e --- /dev/null +++ b/Build/source/texk/web2c/xetexdir/xetex-otmath.ch @@ -0,0 +1,667 @@ +% /****************************************************************************\ +% 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. +% \****************************************************************************/ + +-- redefine mathsy() and mathex() to go to the MATH table for OT fonts +@x +@d mathsy_end(#)==fam_fnt(2+#)]].sc +@d mathsy(#)==font_info[#+param_base[mathsy_end +@d math_x_height==mathsy(5) {height of `\.x'} +@d math_quad==mathsy(6) {\.{18mu}} +@d num1==mathsy(8) {numerator shift-up in display styles} +@d num2==mathsy(9) {numerator shift-up in non-display, non-\.{\\atop}} +@d num3==mathsy(10) {numerator shift-up in non-display \.{\\atop}} +@d denom1==mathsy(11) {denominator shift-down in display styles} +@d denom2==mathsy(12) {denominator shift-down in non-display styles} +@d sup1==mathsy(13) {superscript shift-up in uncramped display style} +@d sup2==mathsy(14) {superscript shift-up in uncramped non-display} +@d sup3==mathsy(15) {superscript shift-up in cramped styles} +@d sub1==mathsy(16) {subscript shift-down if superscript is absent} +@d sub2==mathsy(17) {subscript shift-down if superscript is present} +@d sup_drop==mathsy(18) {superscript baseline below top of large box} +@d sub_drop==mathsy(19) {subscript baseline below bottom of large box} +@d delim1==mathsy(20) {size of \.{\\atopwithdelims} delimiters + in display styles} +@d delim2==mathsy(21) {size of \.{\\atopwithdelims} delimiters in non-displays} +@d axis_height==mathsy(22) {height of fraction lines above the baseline} +@d total_mathsy_params=22 +@y +NB: the access functions here must all put the font # into /f/ for mathsy(). + +The accessors are defined with +define_mathsy_accessor(NAME)(fontdimen-number)(NAME) +because I can't see how to only give the name once, with WEB's limited +macro capabilities. This seems a bit ugly, but it works. + +@d total_mathsy_params=22 + +{the following are OpenType MATH constant indices for use with OT math fonts} +@d scriptPercentScaleDown = 0 +@d scriptScriptPercentScaleDown = 1 +@d delimitedSubFormulaMinHeight = 2 +@d displayOperatorMinHeight = 3 +@d mathLeading = 4 +@d firstMathValueRecord = mathLeading +@d axisHeight = 5 +@d accentBaseHeight = 6 +@d flattenedAccentBaseHeight = 7 +@d subscriptShiftDown = 8 +@d subscriptTopMax = 9 +@d subscriptBaselineDropMin = 10 +@d superscriptShiftUp = 11 +@d superscriptShiftUpCramped = 12 +@d superscriptBottomMin = 13 +@d superscriptBaselineDropMax = 14 +@d subSuperscriptGapMin = 15 +@d superscriptBottomMaxWithSubscript = 16 +@d spaceAfterScript = 17 +@d upperLimitGapMin = 18 +@d upperLimitBaselineRiseMin = 19 +@d lowerLimitGapMin = 20 +@d lowerLimitBaselineDropMin = 21 +@d stackTopShiftUp = 22 +@d stackTopDisplayStyleShiftUp = 23 +@d stackBottomShiftDown = 24 +@d stackBottomDisplayStyleShiftDown = 25 +@d stackGapMin = 26 +@d stackDisplayStyleGapMin = 27 +@d stretchStackTopShiftUp = 28 +@d stretchStackBottomShiftDown = 29 +@d stretchStackGapAboveMin = 30 +@d stretchStackGapBelowMin = 31 +@d fractionNumeratorShiftUp = 32 +@d fractionNumeratorDisplayStyleShiftUp = 33 +@d fractionDenominatorShiftDown = 34 +@d fractionDenominatorDisplayStyleShiftDown = 35 +@d fractionNumeratorGapMin = 36 +@d fractionNumDisplayStyleGapMin = 37 +@d fractionRuleThickness = 38 +@d fractionDenominatorGapMin = 39 +@d fractionDenomDisplayStyleGapMin = 40 +@d skewedFractionHorizontalGap = 41 +@d skewedFractionVerticalGap = 42 +@d overbarVerticalGap = 43 +@d overbarRuleThickness = 44 +@d overbarExtraAscender = 45 +@d underbarVerticalGap = 46 +@d underbarRuleThickness = 47 +@d underbarExtraDescender = 48 +@d radicalVerticalGap = 49 +@d radicalDisplayStyleVerticalGap = 50 +@d radicalRuleThickness = 51 +@d radicalExtraAscender = 52 +@d radicalKernBeforeDegree = 53 +@d radicalKernAfterDegree = 54 +@d lastMathValueRecord = radicalKernAfterDegree +@d radicalDegreeBottomRaisePercent = 55 +@d lastMathConstant = radicalDegreeBottomRaisePercent + + +@d mathsy(#)==font_info[#+param_base[f]].sc + +@d define_mathsy_end(#)== + # := rval; + end +@d define_mathsy_body(#)== + var + f: integer; + rval: scaled; + begin + f := fam_fnt(2 + size_code); + if is_ot_font(f) then + rval := get_native_mathsy_param(f, #) + else + rval := mathsy(#); + define_mathsy_end +@d define_mathsy_accessor(#)==function #(size_code: integer): scaled; define_mathsy_body + +@p define_mathsy_accessor(math_x_height)(5)(math_x_height); +define_mathsy_accessor(math_quad)(6)(math_quad); +define_mathsy_accessor(num1)(8)(num1); +define_mathsy_accessor(num2)(9)(num2); +define_mathsy_accessor(num3)(10)(num3); +define_mathsy_accessor(denom1)(11)(denom1); +define_mathsy_accessor(denom2)(12)(denom2); +define_mathsy_accessor(sup1)(13)(sup1); +define_mathsy_accessor(sup2)(14)(sup2); +define_mathsy_accessor(sup3)(15)(sup3); +define_mathsy_accessor(sub1)(16)(sub1); +define_mathsy_accessor(sub2)(17)(sub2); +define_mathsy_accessor(sup_drop)(18)(sup_drop); +define_mathsy_accessor(sub_drop)(19)(sub_drop); +define_mathsy_accessor(delim1)(20)(delim1); +define_mathsy_accessor(delim2)(21)(delim2); +define_mathsy_accessor(axis_height)(22)(axis_height); +@z + +@x +@d mathex(#)==font_info[#+param_base[fam_fnt(3+cur_size)]].sc +@d default_rule_thickness==mathex(8) {thickness of \.{\\over} bars} +@d big_op_spacing1==mathex(9) {minimum clearance above a displayed op} +@d big_op_spacing2==mathex(10) {minimum clearance below a displayed op} +@d big_op_spacing3==mathex(11) {minimum baselineskip above displayed op} +@d big_op_spacing4==mathex(12) {minimum baselineskip below displayed op} +@d big_op_spacing5==mathex(13) {padding above and below displayed limits} +@d total_mathex_params=13 +@y +@d total_mathex_params=13 + +@d mathex(#)==font_info[#+param_base[f]].sc + +@d define_mathex_end(#)== + # := rval; + end +@d define_mathex_body(#)== + var + f: integer; + rval: scaled; + begin + f := fam_fnt(3 + cur_size); + if is_ot_font(f) then + rval := get_native_mathex_param(f, #) + else + rval := mathex(#); + define_mathex_end +@d define_mathex_accessor(#)==function #:scaled; define_mathex_body + +@p define_mathex_accessor(default_rule_thickness)(8)(default_rule_thickness); +define_mathex_accessor(big_op_spacing1)(9)(big_op_spacing1); +define_mathex_accessor(big_op_spacing2)(10)(big_op_spacing2); +define_mathex_accessor(big_op_spacing3)(11)(big_op_spacing3); +define_mathex_accessor(big_op_spacing4)(12)(big_op_spacing4); +define_mathex_accessor(big_op_spacing5)(13)(big_op_spacing5); +@z + +-- var_delimiter needs to use MathVariants +@x +function var_delimiter(@!d:pointer;@!s:integer;@!v:scaled):pointer; +label found,continue; +var b:pointer; {the box that will be constructed} +@y +procedure stack_glyph_into_box(@!b:pointer;@!f:internal_font_number;@!g:integer); +var p,q:pointer; +begin + p:=get_node(glyph_node_size); + type(p):=whatsit_node; subtype(p):=glyph_node; + native_font(p):=f; native_glyph(p):=g; + set_native_glyph_metrics(p, 1); + link(p):=list_ptr(b); list_ptr(b):=p; + height(b):=height(p); width(b):=width(p); +end; + +procedure stack_glue_into_box(@!b:pointer;@!min,max:scaled); +var p,q:pointer; +begin + q:=new_spec(zero_glue); + width(q):=min; + stretch(q):=max-min; + p:=new_glue(q); + link(p):=list_ptr(b); list_ptr(b):=p; + height(b):=height(p); width(b):=width(p); +end; + +function build_opentype_assembly(@!f:internal_font_number;@!a:void_pointer;@!h:scaled):pointer; + {return a box with height at least |h|, using font |f|, with glyph assembly info from |a|} +var + b:pointer; {the box we're constructing} + n:integer; {the number of repetitions of each extender} + i,j:integer; {indexes} + g:integer; {glyph code} + p:pointer; {temp pointer} + h_max,o,oo,prev_o,min_o:scaled; + no_extenders: boolean; + nat,str:scaled; {natural height, stretch} +begin + b:=new_null_box; + type(b):=vlist_node; + + {figure out how many repeats of each extender to use} + n:=-1; + no_extenders:=true; + min_o:=ot_min_connector_overlap(f); + repeat + n:=n+1; + {calc max possible height with this number of extenders} + h_max:=0; + prev_o:=0; + for i:=0 to ot_part_count(a)-1 do begin + if ot_part_is_extender(a, i) then begin + no_extenders:=false; + for j:=1 to n do begin + o:=ot_part_start_connector(f, a, i); + if min_o<o then o:=min_o; + if prev_o<o then o:=prev_o; + h_max:=h_max-o+ot_part_full_advance(f, a, i); + prev_o:=ot_part_end_connector(f, a, i); + end + end else begin + o:=ot_part_start_connector(f, a, i); + if min_o<o then o:=min_o; + if prev_o<o then o:=prev_o; + h_max:=h_max-o+ot_part_full_advance(f, a, i); + prev_o:=ot_part_end_connector(f, a, i); + end; + end; + until (h_max>=h) or no_extenders; + + {assemble box using |n| copies of each extender, + with appropriate glue wherever an overlap occurs} + prev_o:=0; + for i:=0 to ot_part_count(a)-1 do begin + if ot_part_is_extender(a, i) then begin + for j:=1 to n do begin + o:=ot_part_start_connector(f, a, i); + if prev_o<o then o:=prev_o; + oo:=o; {max overlap} + if min_o<o then o:=min_o; + if oo>0 then stack_glue_into_box(b, -oo, -o); + g:=ot_part_glyph(a, i); + stack_glyph_into_box(b, f, g); + prev_o:=ot_part_end_connector(f, a, i); + end + end else begin + o:=ot_part_start_connector(f, a, i); + if prev_o<o then o:=prev_o; + oo:=o; {max overlap} + if min_o<o then o:=min_o; + if oo>0 then stack_glue_into_box(b, -oo, -o); + g:=ot_part_glyph(a, i); + stack_glyph_into_box(b, f, g); + prev_o:=ot_part_end_connector(f, a, i); + end; + end; + + {find natural height and total stretch of the box} + p:=list_ptr(b); nat:=0; str:=0; + while p<>null do begin + if type(p)=whatsit_node then nat:=nat+height(p)+depth(p) + else if type(p)=glue_node then begin + nat:=nat+width(glue_ptr(p)); + str:=str+stretch(glue_ptr(p)); + end; + p:=link(p); + end; + + {set glue so as to stretch the connections if needed} + depth(b):=0; + if (h>nat) and (str>0) then begin + glue_order(b):=normal; glue_sign(b):=stretching; + glue_set(b):=unfloat((h-nat)/str); + height(b):=nat+round(str*float(glue_set(b))); + end else height(b):=nat; + + build_opentype_assembly:=b; +end; + +function var_delimiter(@!d:pointer;@!s:integer;@!v:scaled):pointer; +label found,continue; +var b:pointer; {the box that will be constructed} +ot_assembly_ptr:void_pointer; +@z + +@x +loop@+ begin @<Look at the variants of |(z,x)|; set |f| and |c| whenever + a better character is found; |goto found| as soon as a + large enough variant is encountered@>; + if large_attempt then goto found; {there were none large enough} + large_attempt:=true; z:=large_fam(d); x:=large_char(d); + end; +found: if f<>null_font then + @<Make variable |b| point to a box for |(f,c)|@> +else begin b:=new_null_box; + width(b):=null_delimiter_space; {use this width if no delimiter was found} + end; +@y +ot_assembly_ptr:=nil; +loop@+ begin @<Look at the variants of |(z,x)|; set |f| and |c| whenever + a better character is found; |goto found| as soon as a + large enough variant is encountered@>; + if large_attempt then goto found; {there were none large enough} + large_attempt:=true; z:=large_fam(d); x:=large_char(d); + end; +found: if f<>null_font then begin + if not is_ot_font(f) then + @<Make variable |b| point to a box for |(f,c)|@> + else begin + {for OT fonts, c is the glyph ID to use} + if ot_assembly_ptr<>nil then + b:=build_opentype_assembly(f, ot_assembly_ptr, v) + else begin + b:=new_null_box; type(b):=vlist_node; list_ptr(b):=get_node(glyph_node_size); + type(list_ptr(b)):=whatsit_node; subtype(list_ptr(b)):=glyph_node; + native_font(list_ptr(b)):=f; native_glyph(list_ptr(b)):=c; + set_native_glyph_metrics(list_ptr(b), 1); + width(b):=width(list_ptr(b)); + height(b):=height(list_ptr(b)); + depth(b):=depth(list_ptr(b)); + end + end +end else begin b:=new_null_box; + width(b):=null_delimiter_space; {use this width if no delimiter was found} + end; +@z + +@x +@ @<Look at the list of characters starting with |x|...@>= +@y +@ @<Look at the list of characters starting with |x|...@>= +if is_ot_font(g) then begin + b:=new_native_character(g, x); + x:=get_native_glyph(b, 0); + free_node(b, native_size(b)); + f:=g; c:=x; w:=0; n:=0; + repeat + y:=get_ot_math_variant(g, x, n, address_of(u)); + if u>w then begin + c:=y; w:=u; + if u>=v then goto found; + end; + n:=n+1; + until u<0; + {if we get here, then we didn't find a big enough glyph; check if the char is extensible} + ot_assembly_ptr:=get_ot_assembly_ptr(g, x); + if ot_assembly_ptr<>nil then goto found; +end else +@z + +-- get radical rule thickness etc from OT +@x +procedure make_radical(@!q:pointer); +var x,@!y:pointer; {temporary registers for box construction} +@!delta,@!clr:scaled; {dimensions involved in the calculation} +begin x:=clean_box(nucleus(q),cramped_style(cur_style)); +if cur_style<text_style then {display style} + clr:=default_rule_thickness+(abs(math_x_height(cur_size)) div 4) +else begin clr:=default_rule_thickness; clr:=clr + (abs(clr) div 4); + end; +y:=var_delimiter(left_delimiter(q),cur_size,height(x)+depth(x)+clr+ + default_rule_thickness); +@y +procedure make_radical(@!q:pointer); +var x,@!y:pointer; {temporary registers for box construction} +f:internal_font_number; +rule_thickness:scaled; {rule thickness} +@!delta,@!clr:scaled; {dimensions involved in the calculation} +begin f:=fam_fnt(3 + cur_size); +if is_ot_font(f) then rule_thickness:=get_ot_math_constant(f,radicalRuleThickness) +else rule_thickness:=default_rule_thickness; +x:=clean_box(nucleus(q),cramped_style(cur_style)); +if is_ot_font(f) then begin +if cur_style<text_style then {display style} + clr:=rule_thickness+(abs(math_x_height(cur_size)) div 4) +else begin clr:=rule_thickness; clr:=clr + (abs(clr) div 4); + end; +end else begin +if cur_style<text_style then {display style} + clr:=get_ot_math_constant(f,radicalDisplayStyleVerticalGap) +else clr:=get_ot_math_constant(f,radicalVerticalGap); +end; +y:=var_delimiter(left_delimiter(q),cur_size,height(x)+depth(x)+clr+rule_thickness); +if is_ot_font(f) then begin + depth(y):=height(y)+depth(y)-rule_thickness; + height(y):=rule_thickness; +end; +@z + +-- use OT spacing parameters from extension font (fam3) rather than hard-coded values +@x +@<Adjust \(s)|shift_up| and |shift_down| for the case of no fraction line@>= +begin if cur_style<text_style then clr:=7*default_rule_thickness +else clr:=3*default_rule_thickness; +@y +@<Adjust \(s)|shift_up| and |shift_down| for the case of no fraction line@>= +begin if is_ot_font(fam_fnt(3+cur_size)) then begin + if cur_style<text_style then clr:=get_ot_math_constant(fam_fnt(3+cur_size), stackDisplayStyleGapMin) + else clr:=get_ot_math_constant(fam_fnt(3+cur_size), stackGapMin); +end else begin + if cur_style<text_style then clr:=7*default_rule_thickness + else clr:=3*default_rule_thickness; +end; +@z + +@x +@<Adjust \(s)|shift_up| and |shift_down| for the case of a fraction line@>= +begin if cur_style<text_style then clr:=3*thickness(q) +else clr:=thickness(q); +delta:=half(thickness(q)); +delta1:=clr-((shift_up-depth(x))-(axis_height(cur_size)+delta)); +delta2:=clr-((axis_height(cur_size)-delta)-(height(z)-shift_down)); +@y +@<Adjust \(s)|shift_up| and |shift_down| for the case of a fraction line@>= +begin if is_ot_font(fam_fnt(3+cur_size)) then begin + delta:=half(thickness(q)); + if cur_style<text_style then clr:=get_ot_math_constant(fam_fnt(3+cur_size), fractionNumDisplayStyleGapMin) + else clr:=get_ot_math_constant(fam_fnt(3+cur_size), fractionNumeratorGapMin); + delta1:=clr-((shift_up-depth(x))-(axis_height(cur_size)+delta)); + if cur_style<text_style then clr:=get_ot_math_constant(fam_fnt(3+cur_size), fractionDenomDisplayStyleGapMin) + else clr:=get_ot_math_constant(fam_fnt(3+cur_size), fractionDenominatorGapMin); + delta2:=clr-((axis_height(cur_size)-delta)-(height(z)-shift_down)); +end else begin + if cur_style<text_style then clr:=3*thickness(q) + else clr:=thickness(q); + delta:=half(thickness(q)); + delta1:=clr-((shift_up-depth(x))-(axis_height(cur_size)+delta)); + delta2:=clr-((axis_height(cur_size)-delta)-(height(z)-shift_down)); +end; +@z + +-- make_op needs to use opentype variant tables to find display size glyphs +@x +function make_op(@!q:pointer):scaled; +var delta:scaled; {offset between subscript and superscript} +@!p,@!v,@!x,@!y,@!z:pointer; {temporary registers for box construction} +@!c:quarterword;@+@!i:four_quarters; {registers for character examination} +@!shift_up,@!shift_down:scaled; {dimensions for box calculation} +begin if (subtype(q)=normal)and(cur_style<text_style) then + subtype(q):=limits; +if math_type(nucleus(q))=math_char then + begin fetch(nucleus(q)); + if (cur_style<text_style)and(char_tag(cur_i)=list_tag) then {make it larger} + begin c:=rem_byte(cur_i); i:=orig_char_info(cur_f)(c); + if char_exists(i) then + begin cur_c:=c; cur_i:=i; character(nucleus(q)):=c; + end; + end; + delta:=char_italic(cur_f)(cur_i); x:=clean_box(nucleus(q),cur_style); + if (math_type(subscr(q))<>empty)and(subtype(q)<>limits) then + width(x):=width(x)-delta; {remove italic correction} + shift_amount(x):=half(height(x)-depth(x)) - axis_height(cur_size); + {center vertically} + math_type(nucleus(q)):=sub_box; info(nucleus(q)):=x; + end +else delta:=0; +if subtype(q)=limits then + @<Construct a box with limits above and below it, skewed by |delta|@>; +make_op:=delta; +end; +@y +function make_op(@!q:pointer):scaled; +var delta:scaled; {offset between subscript and superscript} +@!p,@!v,@!x,@!y,@!z:pointer; {temporary registers for box construction} +@!c:quarterword;@+@!i:four_quarters; {registers for character examination} +@!shift_up,@!shift_down:scaled; {dimensions for box calculation} +@!h1,@!h2:scaled; {height of original text-style symbol and possible replacement} +@!n,@!g:integer; {potential variant index and glyph code} +begin if (subtype(q)=normal)and(cur_style<text_style) then + subtype(q):=limits; +delta:=0; +if math_type(nucleus(q))=math_char then + begin fetch(nucleus(q)); + if not is_ot_font(cur_f) then begin + if (cur_style<text_style)and(char_tag(cur_i)=list_tag) then {make it larger} + begin c:=rem_byte(cur_i); i:=orig_char_info(cur_f)(c); + if char_exists(i) then + begin cur_c:=c; cur_i:=i; character(nucleus(q)):=c; + end; + end; + delta:=char_italic(cur_f)(cur_i); + end; + x:=clean_box(nucleus(q),cur_style); + if is_ot_font(cur_f) then begin + p:=list_ptr(x); + if (type(p)=whatsit_node) and (subtype(p)=glyph_node) then begin + if cur_style<text_style then begin + {try to replace the operator glyph with a variant at least 25% taller} + h1:=height(p)+depth(p); + c:=native_glyph(p); + n:=1; + repeat + g:=get_ot_math_variant(cur_f, c, n, address_of(h2)); + if h2>0 then native_glyph(p):=g; + incr(n); + until (h2<0) or (h2>(h1*5)/4); + set_native_glyph_metrics(p, 1); + end; + width(x):=width(p); height(x):=height(p); depth(x):=depth(p); + delta:=get_ot_math_ital_corr(cur_f, native_glyph(p)); + end + end; + if (math_type(subscr(q))<>empty)and(subtype(q)<>limits) then + width(x):=width(x)-delta; {remove italic correction} + shift_amount(x):=half(height(x)-depth(x)) - axis_height(cur_size); + {center vertically} + math_type(nucleus(q)):=sub_box; info(nucleus(q)):=x; + end; +if subtype(q)=limits then + @<Construct a box with limits above and below it, skewed by |delta|@>; +make_op:=delta; +end; +@z + +-- make glyph nodes rather than native_word_nodes here +@x +@ @<Create a character node |p| for |nucleus(q)|...@>= +begin fetch(nucleus(q)); +if is_native_font(cur_f) then begin + delta:=0; p:=new_native_character(cur_f, qo(cur_c)); +@y +@ @<Create a character node |p| for |nucleus(q)|...@>= +begin fetch(nucleus(q)); +if is_native_font(cur_f) then begin + z:=new_native_character(cur_f, qo(cur_c)); + p:=get_node(glyph_node_size); + type(p):=whatsit_node; subtype(p):=glyph_node; + native_font(p):=cur_f; native_glyph(p):=get_native_glyph(z, 0); + set_native_glyph_metrics(p, 1); + free_node(z, native_size(z)); + delta:=0; {FIXME} +@z + +-- make_scripts needs to treat native_text like char_node, not box +@x +@ The purpose of |make_scripts(q,delta)| is to attach the subscript and/or +superscript of noad |q| to the list that starts at |new_hlist(q)|, +given that subscript and superscript aren't both empty. The superscript +will appear to the right of the subscript by a given distance |delta|. + +We set |shift_down| and |shift_up| to the minimum amounts to shift the +baseline of subscripts and superscripts based on the given nucleus. + +@<Declare math...@>= +procedure make_scripts(@!q:pointer;@!delta:scaled); +var p,@!x,@!y,@!z:pointer; {temporary registers for box construction} +@!shift_up,@!shift_down,@!clr:scaled; {dimensions in the calculation} +@!t:integer; {subsidiary size code} +begin p:=new_hlist(q); +if is_char_node(p) then +@y +@ The purpose of |make_scripts(q,delta)| is to attach the subscript and/or +superscript of noad |q| to the list that starts at |new_hlist(q)|, +given that subscript and superscript aren't both empty. The superscript +will appear to the right of the subscript by a given distance |delta|. + +We set |shift_down| and |shift_up| to the minimum amounts to shift the +baseline of subscripts and superscripts based on the given nucleus. + +@<Declare math...@>= +procedure make_scripts(@!q:pointer;@!delta:scaled); +var p,@!x,@!y,@!z:pointer; {temporary registers for box construction} +@!shift_up,@!shift_down,@!clr:scaled; {dimensions in the calculation} +@!t:integer; {subsidiary size code} +begin p:=new_hlist(q); +if is_char_node(p) or (p<>null and is_native_word_node(p)) then +@z + +-- we allow either TFMs with lots of fontdimens or OpenType fonts +@x +@ @<Check that the necessary fonts...@>= +if (font_params[fam_fnt(2+text_size)]<total_mathsy_params)or@| + (font_params[fam_fnt(2+script_size)]<total_mathsy_params)or@| + (font_params[fam_fnt(2+script_script_size)]<total_mathsy_params) then +@y +@ @<Check that the necessary fonts...@>= +if ((font_params[fam_fnt(2+text_size)]<total_mathsy_params) + and (not is_ot_font(fam_fnt(2+text_size)))) or@| + ((font_params[fam_fnt(2+script_size)]<total_mathsy_params) + and (not is_ot_font(fam_fnt(2+script_size)))) or@| + ((font_params[fam_fnt(2+script_script_size)]<total_mathsy_params) + and (not is_ot_font(fam_fnt(2+script_script_size)))) then +@z + +@x +else if (font_params[fam_fnt(3+text_size)]<total_mathex_params)or@| + (font_params[fam_fnt(3+script_size)]<total_mathex_params)or@| + (font_params[fam_fnt(3+script_script_size)]<total_mathex_params) then +@y +else if ((font_params[fam_fnt(3+text_size)]<total_mathex_params) + and (not is_ot_font(fam_fnt(3+text_size)))) or@| + ((font_params[fam_fnt(3+script_size)]<total_mathex_params) + and (not is_ot_font(fam_fnt(3+script_size)))) or@| + ((font_params[fam_fnt(3+script_script_size)]<total_mathex_params) + and (not is_ot_font(fam_fnt(3+script_script_size)))) then +@z + +-- need to be able to output glyph nodes in a vlist (for extensible stacks) +@x +@ @<Output the whatsit node |p| in a vlist@>= +begin + case subtype(p) of +@y +@ @<Output the whatsit node |p| in a vlist@>= +begin + case subtype(p) of + glyph_node: begin + cur_v:=cur_v+height(p); + cur_h:=left_edge; + + { synch DVI state to TeX state } + synch_h; synch_v; + f := native_font(p); + if f<>dvi_f then @<Change font |dvi_f| to |f|@>; + + dvi_out(set_glyph_string); + dvi_four(0); { width } + dvi_two(1); { glyph count } + dvi_four(0); { x-offset as fixed point } + dvi_two(native_glyph(p)); + + cur_v:=cur_v+depth(p); + cur_h:=left_edge; + end; +@z diff --git a/Build/source/texk/web2c/xetexdir/xetex.defines b/Build/source/texk/web2c/xetexdir/xetex.defines index d29e0fe281d..222ed2717a0 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.defines +++ b/Build/source/texk/web2c/xetexdir/xetex.defines @@ -35,6 +35,7 @@ authorization from SIL International. @define type voidpointer; @define function getnativechar(); @define procedure setnativechar(); +@define function getnativeglyph(); @define procedure setnativemetrics(); @define procedure setjustifiednativeglyphs(); @define procedure setnativeglyphmetrics(); @@ -81,12 +82,29 @@ authorization from SIL International. @define procedure getnativecharsidebearings(); @define function getnativeitaliccorrection(); @define function getnativeglyphitaliccorrection(); +@define procedure printglyphname(); +@define function getfontcharrange(); @define function getnativecharwd(); @define function getnativecharht(); @define function getnativechardp(); @define function getnativecharic(); +@define function getnativemathsyparam(); +@define function getnativemathexparam(); +@define function getotmathconstant(); +@define function getotmathvariant(); +@define function getotassemblyptr(); +@define function getotmathitalcorr(); + +@define function otpartcount(); +@define function otpartglyph(); +@define function otpartstartconnector(); +@define function otpartendconnector(); +@define function otpartfulladvance(); +@define function otpartisextender(); +@define function otminconnectoroverlap(); + @define function setfamilyfield(); @define function setclassfield(); @define function mathfamfield(); @@ -131,6 +149,8 @@ authorization from SIL International. @define function dField(); @define function xField(); @define function yField(); +@define function txField(); +@define function tyField(); @define function wdField(); @define function htField(); @define function applymapping(); diff --git a/Build/source/texk/web2c/xetexdir/xetex.h b/Build/source/texk/web2c/xetexdir/xetex.h index 2078449f499..951ac4d7632 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.h +++ b/Build/source/texk/web2c/xetexdir/xetex.h @@ -46,9 +46,13 @@ authorization from SIL International. #define getnativeitaliccorrection(p) get_native_ital_corr(&(mem[p])) #define getnativeglyphitaliccorrection(p) get_native_glyph_ital_corr(&(mem[p])) +#define getnativeglyph(p,i) get_native_glyph_id(&(mem[p]), i) + #define makexdvglypharraydata(p) makeXDVGlyphArrayData(&(mem[p])) #define xdvbufferbyte(i) xdvbuffer[i] +void* getotassemblyptr(int f, int g); /* function in XeTeXOTMath.cpp */ + #define pic_node_size 8 #define deref(p) (*(p)) @@ -59,12 +63,6 @@ authorization from SIL International. #define dviopenout(f) open_dvi_output(&(f)) -#define readcint1(x) (x).cint1 -#define setcint1(x,y) (x).cint1 = (y) - -#define delcode1(x) readcint1(eqtb[xetexdelcodebase+(x)]) -#define setdelcode1(x,y) setcint1(eqtb[xetexdelcodebase+(x)],(y)) - #define casttoptr(x) (void*)(x) #define casttointeger(x) (long)(x) #define glyphinfobyte(p,k) ((unsigned char*)p)[k] diff --git a/Build/source/texk/web2c/xetexdir/xetex.mk b/Build/source/texk/web2c/xetexdir/xetex.mk index 2c21864f110..ac6e871d475 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.mk +++ b/Build/source/texk/web2c/xetexdir/xetex.mk @@ -152,6 +152,7 @@ xetex_ot_layout_o = \ XeTeXFontMgr.o \ XeTeXLayoutInterface.o XeTeXOTLayoutEngine.o \ XeTeXFontInst.o cmaps.o FontTableCache.o \ + XeTeXOTMath.o \ $(xetex_platform_layout_o) XeTeXLayoutInterface.o: $(srcdir)/xetexdir/XeTeXLayoutInterface.cpp $(XeTeXFontHdrs) @@ -179,6 +180,9 @@ XeTeXFontInst_Mac.o: $(srcdir)/xetexdir/XeTeXFontInst_Mac.cpp $(XeTeXFontHdrs) XeTeXFontInst_FT2.o: $(srcdir)/xetexdir/XeTeXFontInst_FT2.cpp $(XeTeXFontHdrs) $(CXX) $(ICUCFLAGS) $(FTFLAGS) $(ALL_CXXFLAGS) $(XETEX_DEFINES) -c $< -o $@ +XeTeXOTMath.o: $(srcdir)/xetexdir/XeTeXOTMath.cpp $(XeTeXFontHdrs) + $(CXX) $(ICUCFLAGS) $(FTFLAGS) $(ALL_CXXFLAGS) $(XETEX_DEFINES) -c $< -o $@ + # special rules for files that need the TECkit headers as well XeTeX_ext.o: $(srcdir)/xetexdir/XeTeX_ext.c xetexd.h $(compile) $(ICUCFLAGS) $(FTFLAGS) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@ @@ -189,7 +193,7 @@ trans.o: $(srcdir)/xetexdir/trans.c $(compile) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@ # Making xetex. -xetex: $(xetex_o) $(xetex_add_o) $(xetex_images_o) $(xetex_ot_layout_o) $(EXTRADEPS) +xetex: $(xetex_o) $(xetex_add_o) $(xetex_images_o) $(xetex_ot_layout_o) $(xetexlibs) $(EXTRADEPS) @CXXHACKLINK@ $(xetex_o) $(xetex_add_o) $(xetex_images_o) $(xetex_ot_layout_o) \ $(socketlibs) $(xetexlibs) $(EXTRALIBS) \ @CXXHACKLDLIBS@ @CXXLDEXTRA@ @@ -218,7 +222,8 @@ xetex_web_srcs = $(srcdir)/tex.web \ $(srcdir)/etexdir/tex.ech \ $(srcdir)/xetexdir/xetex-new.ch \ $(srcdir)/xetexdir/xetex-noenc.ch \ - $(srcdir)/xetexdir/xetex-upwards.ch + $(srcdir)/xetexdir/xetex-upwards.ch \ + $(srcdir)/xetexdir/xetex-otmath.ch xetex.web: tie xetexdir/xetex.mk $(xetex_web_srcs) $(TIE) -m xetex.web $(xetex_web_srcs) |