From 5510e0bf8ad6881494129b795d1ad7286fd70b7a Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 17 Apr 2008 14:26:29 +0000 Subject: xetex 0.996-patch2: backported fixes from svn r.414, 449, 460, 466, 467, 468-9, 510, 436, 518, 526, 510, 557, 572, 580, 579, 634, 541-3, 589 git-svn-id: svn://tug.org/texlive/branches/branch2007@7473 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/web2c/etexdir/etex.ch | 22 +- Build/source/texk/web2c/lib/texmfmp.c | 57 +++- Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp | 144 +++++---- Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h | 8 +- .../texk/web2c/xetexdir/XeTeXLayoutInterface.cpp | 7 +- .../texk/web2c/xetexdir/XeTeXLayoutInterface.h | 19 +- .../texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp | 2 +- Build/source/texk/web2c/xetexdir/XeTeX_ext.c | 85 ++++-- Build/source/texk/web2c/xetexdir/XeTeX_ext.h | 1 + Build/source/texk/web2c/xetexdir/XeTeX_mac.c | 25 ++ Build/source/texk/web2c/xetexdir/XeTeX_pic.c | 16 + Build/source/texk/web2c/xetexdir/appleGlyphNames.c | 2 +- Build/source/texk/web2c/xetexdir/pdfimage.cpp | 22 ++ Build/source/texk/web2c/xetexdir/pdfimage.h | 2 + Build/source/texk/web2c/xetexdir/pool2c.pl | 74 +++++ Build/source/texk/web2c/xetexdir/xetex-new.ch | 327 +++++++++++++-------- Build/source/texk/web2c/xetexdir/xetex.defines | 2 + Build/source/texk/web2c/xetexdir/xetex.mk | 24 +- Build/source/texk/web2c/xetexdir/xetexextra.in | 2 +- 19 files changed, 615 insertions(+), 226 deletions(-) create mode 100644 Build/source/texk/web2c/xetexdir/pool2c.pl diff --git a/Build/source/texk/web2c/etexdir/etex.ch b/Build/source/texk/web2c/etexdir/etex.ch index 74c19e79057..d887bf00288 100644 --- a/Build/source/texk/web2c/etexdir/etex.ch +++ b/Build/source/texk/web2c/etexdir/etex.ch @@ -29,7 +29,7 @@ % (pdftexdir/pdftex.ch). Consequently, changes in these files have to be % coordinated. -% e-TeX is copyright (C) 1999-2004 by P. Breitenlohner (1994,98 by the NTS +% e-TeX is copyright (C) 1999-2008 by P. Breitenlohner (1994,98 by the NTS % team); all rights are reserved. Copying of this file is authorized only if % (1) you are P. Breitenlohner, or if (2) you make absolutely no changes to % your copy. (Programs such as TIE allow the application of several change @@ -116,6 +116,9 @@ % direction typesetting; % fixed a bug in the revised glue rounding code, detected by % Tigran Aivazian , Oct 2004. +% Version 2.3 development was started in Feb 2008; released in Mon Year. +% fixed a bug in hyph_code handling (\savinghyphcodes) +% reported by Vladimir Volovich , Feb 2008. % Although considerable effort has been expended to make the e-TeX program % correct and reliable, no warranty is implied; the author disclaims any @@ -3020,13 +3023,12 @@ if (format_ident=0)or(buffer[loc]="&") then if eTeX_ex then wterm_ln('entering extended mode'); @z %--------------------------------------- -@x [53] m.1363 l.24757 - e-TeX hyph_codes -adv_past(s) +@x [53] m.1362 l.24751 adv_past - e-TeX hyph_codes + begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end @y -if subtype(s)=language_node then - begin cur_lang:=what_lang(s); l_hyf:=what_lhm(s); r_hyf:=what_rhm(s); - set_hyph_index; - end + begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#); + set_hyph_index; + end @z %--------------------------------------- @x [54] m.1379 l.24945 - e-TeX additions @@ -5915,7 +5917,7 @@ fields in the active nodes. @!best_pl_glue:array[very_loose_fit..tight_fit] of scaled; {corresponding glue stretch or shrink} -@ The new algorithm for the last line requires that the stretchability +@ The new algorithm for the last line requires that the stretchability of |par_fill_skip| is infinite and the stretchability of |left_skip| plus |right_skip| is finite. @@ -5966,10 +5968,10 @@ if arith_error then if active_short(r)>0 then g:=max_dimen@+else g:=-max_dimen; if g>0 then @ + compute the corresponding |fit_class|, and |goto found|@> else if g<0 then @; + compute the corresponding |fit_class|, and |goto found|@>; not_found:end @ These badness computations are rather similar to those of the standard diff --git a/Build/source/texk/web2c/lib/texmfmp.c b/Build/source/texk/web2c/lib/texmfmp.c index 12307761463..494b353c08c 100644 --- a/Build/source/texk/web2c/lib/texmfmp.c +++ b/Build/source/texk/web2c/lib/texmfmp.c @@ -1953,22 +1953,65 @@ compare_paths P2C(const_string, p1, const_string, p2) return ret; } -#ifdef XeTeX -#define strstartar strstart -#endif +#ifdef XeTeX /* the string pool is UTF-16 but we want a UTF-8 string */ + +string +gettexstring P1C(strnumber, s) +{ + unsigned bytesToWrite = 0; + poolpointer len, i, j; + string name; + len = strstart[s + 1 - 65536L] - strstart[s - 65536L]; + name = (string)xmalloc(len * 3 + 1); /* max UTF16->UTF8 expansion (code units, not bytes) */ + for (i = 0, j = 0; i < len; i++) { + unsigned c = strpool[i + strstart[s - 65536L]]; + if (c >= 0xD800 && c <= 0xDBFF) { + unsigned lo = strpool[++i + strstart[s - 65536L]]; + if (lo >= 0xDC00 && lo <= 0xDFFF) + c = (c - 0xD800) * 0x0400 + lo - 0xDC00; + else + c = 0xFFFD; + } + if (c < 0x80) + bytesToWrite = 1; + else if (c < 0x800) + bytesToWrite = 2; + else if (c < 0x10000) + bytesToWrite = 3; + else if (c < 0x110000) + bytesToWrite = 4; + else { + bytesToWrite = 3; + c = 0xFFFD; + } + + j += bytesToWrite; + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: name[--j] = ((c | 0x80) & 0xBF); c >>= 6; + case 3: name[--j] = ((c | 0x80) & 0xBF); c >>= 6; + case 2: name[--j] = ((c | 0x80) & 0xBF); c >>= 6; + case 1: name[--j] = (c | firstByteMark[bytesToWrite]); + } + j += bytesToWrite; + } + name[j] = 0; + return name; +} + +#else string gettexstring P1C(strnumber, s) { poolpointer len; string name; -#if !defined(Omega) && !defined(eOmega) && !defined(Aleph) && !defined(XeTeX) +#if !defined(Omega) && !defined(eOmega) && !defined(Aleph) len = strstart[s + 1] - strstart[s]; #else len = strstartar[s + 1 - 65536L] - strstartar[s - 65536L]; #endif name = (string)xmalloc (len + 1); -#if !defined(Omega) && !defined(eOmega) && !defined(Aleph) && !defined(XeTeX) +#if !defined(Omega) && !defined(eOmega) && !defined(Aleph) strncpy (name, (string)&strpool[strstart[s]], len); #else { @@ -1981,9 +2024,7 @@ gettexstring P1C(strnumber, s) return name; } -#ifdef XeTeX -#undef strstartar -#endif +#endif /* not XeTeX */ boolean isnewsource P2C(strnumber, srcfilename, int, lineno) diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp index 62c787da5bb..dde4f26a80a 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp @@ -34,7 +34,6 @@ authorization from SIL International. #include "XeTeXFontMgr_FC.h" #endif -#include "XeTeXLayoutInterface.h" #include "XeTeXswap.h" #include "Features.h" @@ -44,6 +43,8 @@ authorization from SIL International. #include +extern Fixed loadedfontdesignsize; + XeTeXFontMgr* XeTeXFontMgr::sFontManager = NULL; char XeTeXFontMgr::sReqEngine = 0; @@ -83,17 +84,22 @@ XeTeXFontMgr::Terminate() PlatformFontRef XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) - // ptSize is in TeX points + // ptSize is in TeX points, or negative for 'scaled' factor // "variant" string will be shortened (in-place) by removal of /B and /I if present { std::string nameStr(name); Font* font = NULL; + int dsize = 100; + loadedfontdesignsize = 655360L; + for (int pass = 0; pass < 2; ++pass) { // try full name as given std::map::iterator i = nameToFont.find(nameStr); if (i != nameToFont.end()) { font = i->second; + if (font->opSizeInfo.designSize != 0) + dsize = font->opSizeInfo.designSize; break; } @@ -107,6 +113,8 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) i = f->second->styles->find(style); if (i != f->second->styles->end()) { font = i->second; + if (font->opSizeInfo.designSize != 0) + dsize = font->opSizeInfo.designSize; break; } } @@ -116,6 +124,8 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) i = psNameToFont.find(nameStr); if (i != psNameToFont.end()) { font = i->second; + if (font->opSizeInfo.designSize != 0) + dsize = font->opSizeInfo.designSize; break; } @@ -179,7 +189,7 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) Family* parent = font->parent; // if there are variant requests, try to apply them - // and delete B or I codes from the string + // and delete B, I, and S=... codes from the string, just retain /engine option sReqEngine = 0; bool reqBold = false; bool reqItal = false; @@ -248,9 +258,6 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) ++cp; } } - if (varString.length() > 0 && *(varString.end() - 1) != '/') - varString.append("/"); - varString.append(start, cp); goto skip_to_slash; } @@ -359,8 +366,10 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) } // if there's optical size info, try to apply it - if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize != 0.0) { - ptSize = ptSize * 720 / 72.27; // convert TeX points to PS decipoints for comparison with the opSize values + if (ptSize < 0.0) + ptSize = dsize / 10.0; + if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize > 0.0) { + ptSize = ptSize * 10.0; // convert to decipoints for comparison with the opSize values double bestMismatch = my_fmax(font->opSizeInfo.minSize - ptSize, ptSize - font->opSizeInfo.maxSize); if (bestMismatch > 0.0) { Font* bestMatch = font; @@ -378,6 +387,9 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) font = bestMatch; } } + + if (font != NULL && font->opSizeInfo.designSize != 0) + loadedfontdesignsize = (font->opSizeInfo.designSize << 16L) / 10; return font->fontRef; } @@ -450,58 +462,82 @@ XeTeXFontMgr::bestMatchFromFamily(const Family* fam, int wt, int wd, int slant) return bestMatch; } +const XeTeXFontMgr::OpSizeRec* +XeTeXFontMgr::getOpSizePtr(XeTeXFont font) +{ + const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)getFontTablePtr(font, LE_GPOS_TABLE_TAG); + if (gposTable != NULL) { + 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) { + 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 */ + for (int i = 0; i < 2; ++i) { + if (i == 0) + pSizeRec = (const OpSizeRec*)((char*)feature + offset); + else + pSizeRec = (const OpSizeRec*)((char*)featureListTable + offset); + if (SWAP(pSizeRec->designSize) == 0) + continue; // incorrect 'size' feature format + if (SWAP(pSizeRec->subFamilyID) == 0 + && SWAP(pSizeRec->nameCode) == 0 + && SWAP(pSizeRec->minSize) == 0 + && SWAP(pSizeRec->maxSize) == 0) + return pSizeRec; // feature is valid, but no 'size' range + if (SWAP(pSizeRec->designSize) < SWAP(pSizeRec->minSize)) // check values are valid + continue; // else try different interpretation + if (SWAP(pSizeRec->designSize) > SWAP(pSizeRec->maxSize)) + continue; + if (SWAP(pSizeRec->maxSize) < SWAP(pSizeRec->minSize)) + continue; + if (SWAP(pSizeRec->nameCode) < 256) + continue; + if (SWAP(pSizeRec->nameCode) > 32767) + continue; + return pSizeRec; + } + } + } + } + + return NULL; +} + +double +XeTeXFontMgr::getDesignSize(XeTeXFont font) +{ + const OpSizeRec* pSizeRec = getOpSizePtr(font); + if (pSizeRec != NULL) + return SWAP(pSizeRec->designSize) / 10.0; + else + return 10.0; +} + void XeTeXFontMgr::getOpSizeRecAndStyleFlags(Font* theFont) { XeTeXFont font = createFont(theFont->fontRef, 655360); if (font != 0) { - const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)getFontTablePtr(font, LE_GPOS_TABLE_TAG); - if (gposTable != NULL) { - 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) { - 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 */ - for (int i = 0; i < 2; ++i) { - if (i == 0) - pSizeRec = (const OpSizeRec*)((char*)feature + offset); - else - pSizeRec = (const OpSizeRec*)((char*)featureListTable + offset); - if (SWAP(pSizeRec->designSize) == 0) - continue; // incorrect 'size' feature format - if (SWAP(pSizeRec->subFamilyID) == 0 - && SWAP(pSizeRec->nameCode) == 0 - && SWAP(pSizeRec->minSize) == 0 - && SWAP(pSizeRec->maxSize) == 0) - break; // feature is valid, but no 'size' range - if (SWAP(pSizeRec->designSize) < SWAP(pSizeRec->minSize)) - continue; - if (SWAP(pSizeRec->designSize) > SWAP(pSizeRec->maxSize)) - continue; - if (SWAP(pSizeRec->maxSize) <= SWAP(pSizeRec->minSize)) - continue; - if (SWAP(pSizeRec->nameCode) < 256) - continue; - if (SWAP(pSizeRec->nameCode) > 32767) - continue; - // looks like we've found a usable feature! - theFont->opSizeInfo.designSize = SWAP(pSizeRec->designSize); - theFont->opSizeInfo.subFamilyID = SWAP(pSizeRec->subFamilyID); - theFont->opSizeInfo.nameCode = SWAP(pSizeRec->nameCode); - theFont->opSizeInfo.minSize = SWAP(pSizeRec->minSize); - theFont->opSizeInfo.maxSize = SWAP(pSizeRec->maxSize); - break; - } - break; - } - } + const OpSizeRec* pSizeRec = getOpSizePtr(font); + if (pSizeRec != NULL) { + theFont->opSizeInfo.designSize = SWAP(pSizeRec->designSize); + if (SWAP(pSizeRec->subFamilyID) == 0 + && SWAP(pSizeRec->nameCode) == 0 + && SWAP(pSizeRec->minSize) == 0 + && SWAP(pSizeRec->maxSize) == 0) + goto done_size; // feature is valid, but no 'size' range + theFont->opSizeInfo.subFamilyID = SWAP(pSizeRec->subFamilyID); + theFont->opSizeInfo.nameCode = SWAP(pSizeRec->nameCode); + theFont->opSizeInfo.minSize = SWAP(pSizeRec->minSize); + theFont->opSizeInfo.maxSize = SWAP(pSizeRec->maxSize); } + done_size: const OS2TableHeader* os2Table = (const OS2TableHeader*)getFontTablePtr(font, LE_OS_2_TABLE_TAG); if (os2Table != NULL) { diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h index b82194afb07..44e2bcade75 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h @@ -43,6 +43,8 @@ typedef ATSFontRef PlatformFontRef; typedef FcPattern* PlatformFontRef; #endif +#include "XeTeXLayoutInterface.h" + #ifdef __cplusplus /* allow inclusion in plain C files just to get the typedefs above */ #include @@ -83,6 +85,7 @@ public: const char** famName, const char** styName) const; // return Postscript, family, and style names, for use in .xdv + double getDesignSize(XeTeXFont font); char getReqEngine() const; // return the requested rendering technology for the most recent findFont @@ -118,7 +121,8 @@ protected: , parent(NULL) , fontRef(ref), weight(0), width(0), slant(0) , isReg(false), isBold(false), isItalic(false) - { opSizeInfo.subFamilyID = 0; } + { opSizeInfo.subFamilyID = 0; + opSizeInfo.designSize = 100; } /* default to 10bp */ ~Font() { delete fullName; delete psName; } @@ -181,6 +185,8 @@ protected: void prependToList(std::list* list, const char* str); void addToMaps(PlatformFontRef platformFont, const NameCollection* names); + const OpSizeRec* getOpSizePtr(XeTeXFont font); + virtual void getOpSizeRecAndStyleFlags(Font* theFont); virtual void searchForHostPlatformFonts(const std::string& name) = 0; diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp index a591d7a05a4..b5d179dd5fe 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp @@ -144,6 +144,11 @@ const char* getFullName(PlatformFontRef fontRef) return XeTeXFontMgr::GetFontManager()->getFullName(fontRef); } +double getDesignSize(XeTeXFont font) +{ + return XeTeXFontMgr::GetFontManager()->getDesignSize(font); +} + const char* getFontFilename(XeTeXLayoutEngine engine) { return engine->font->getFilename(); @@ -479,7 +484,7 @@ findGlyphInPostTable(const char* buffer, int tableSize, const char* glyphName) switch (SWAP(p->format)) { case 0x00010000: { - char* cp; + const char* cp; while ((cp = appleGlyphNames[g]) != 0) { if (strcmp(glyphName, cp) == 0) return g; diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h index d92cca16d91..620eb050773 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h @@ -28,10 +28,22 @@ use or other dealings in this Software without prior written authorization from SIL International. \****************************************************************************/ +#ifndef XETEX_LAYOUT_INTERFACE_H +#define XETEX_LAYOUT_INTERFACE_H 1 + #ifdef XETEX_MAC #include #endif +#ifdef __cplusplus +extern "C" { +#endif +typedef struct XeTeXFont_rec* XeTeXFont; +typedef struct XeTeXLayoutEngine_rec* XeTeXLayoutEngine; +#ifdef __cplusplus +}; +#endif + #include "XeTeX_ext.h" #include "XeTeXFontMgr.h" @@ -39,9 +51,6 @@ authorization from SIL International. extern "C" { #endif -typedef struct XeTeXFont_rec* XeTeXFont; -typedef struct XeTeXLayoutEngine_rec* XeTeXLayoutEngine; - extern char gPrefEngine; int getCachedGlyphBBox(UInt16 fontID, UInt16 glyphID, GlyphBBox* bbox); @@ -67,6 +76,7 @@ const char* getFullName(PlatformFontRef fontRef); const char* getFontFilename(XeTeXLayoutEngine engine); void getNames(PlatformFontRef fontRef, const char** psName, const char** famName, const char** styName); +double getDesignSize(XeTeXFont font); void deleteFont(XeTeXFont font); @@ -139,3 +149,6 @@ int getFontCharRange(XeTeXLayoutEngine engine, int reqFirst); #ifdef __cplusplus }; #endif + +#endif /* XETEX_LAYOUT_INTERFACE_H */ + diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp index d8ef3ed3a04..5583b31c337 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp @@ -129,7 +129,7 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory break; case arabScriptCode: - case hebrScriptCode: +// case hebrScriptCode: result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags); break; diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c index a4b467bb10c..24d5bd93bb8 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c @@ -710,9 +710,9 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha if (strncmp(cp1, "vertical", 8) == 0) { cp3 = cp2; - if (*cp3 == ';' || *cp3 == ':') + if (*cp3 == ';' || *cp3 == ':' || *cp3 == ',') --cp3; - while (*cp3 == ' ' || *cp3 == '\t') + while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t') --cp3; if (*cp3) ++cp3; @@ -763,10 +763,11 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha } static void -splitFontName(char* name, char** var, char** feat, char** end) +splitFontName(char* name, char** var, char** feat, char** end, int* index) { *var = NULL; *feat = NULL; + *index = 0; if (*name == '[') { int withinFileName = 1; #ifdef WIN32 @@ -784,8 +785,12 @@ splitFontName(char* name, char** var, char** feat, char** end) #ifdef WIN32 && !((name - start == 1) && isalpha(*start)) #endif - ) - *var = name; + ) { + ++name; + while (*name >= '0' && *name <= '9') + *index = *index * 10 + *name++ - '0'; + --name; + } else if (!withinFileName && *feat == NULL) *feat = name; } @@ -811,9 +816,9 @@ splitFontName(char* name, char** var, char** feat, char** end) void* findnativefont(unsigned char* uname, integer scaled_size) - /* scaled_size here is in TeX points */ + /* scaled_size here is in TeX points, or is a negative integer for 'scaled' */ { - void* rval = 0; + void* rval = NULL; char* nameString; char* var; char* feat; @@ -823,13 +828,13 @@ findnativefont(unsigned char* uname, integer scaled_size) char* featString = NULL; PlatformFontRef fontRef; XeTeXFont font; + int index = 0; loadedfontmapping = NULL; loadedfontflags = 0; loadedfontletterspace = 0; - splitFontName(name, &var, &feat, &end); - + splitFontName(name, &var, &feat, &end, &index); nameString = xmalloc(var - name + 1); strncpy(nameString, name, var - name); nameString[var - name] = 0; @@ -854,16 +859,22 @@ findnativefont(unsigned char* uname, integer scaled_size) if (path == NULL) path = kpse_find_file(nameString + 1, kpse_type1_format, 0); if (path != NULL) { - int index = 0; - if (varString != NULL) { - char* cp; - for (cp = varString; *cp && isdigit(*cp); ++cp) - index = index * 10 + *cp - '0'; + if (scaled_size < 0) { + font = createFontFromFile(path, index, 655360L); + if (font != NULL) { + Fixed dsize = X2Fix(getDesignSize(font)); + if (scaled_size == -1000) + scaled_size = dsize; + else + scaled_size = zxnoverd(dsize, -scaled_size, 1000); + deleteFont(font); + } } font = createFontFromFile(path, index, scaled_size); if (font != NULL) { + loadedfontdesignsize = X2Fix(getDesignSize(font)); rval = loadOTfont(0, font, scaled_size, featString); - if (rval == 0) + if (rval == NULL) deleteFont(font); } } @@ -883,6 +894,18 @@ findnativefont(unsigned char* uname, integer scaled_size) nameoffile = xmalloc(namelength + 4); /* +2 would be correct: initial space, final NUL */ nameoffile[0] = ' '; strcpy((char*)nameoffile + 1, fullName); + + if (scaled_size < 0) { + font = createFont(fontRef, scaled_size); + if (font != NULL) { + Fixed dsize = X2Fix(getDesignSize(font)); + if (scaled_size == -1000) + scaled_size = dsize; + else + scaled_size = zxnoverd(dsize, -scaled_size, 1000); + deleteFont(font); + } + } #ifdef XETEX_MAC /* decide whether to use AAT or OpenType rendering with this font */ @@ -1568,7 +1591,7 @@ measure_native_node(void* pNode, int use_glyph_metrics) for (runIndex = 0; runIndex < nRuns; ++runIndex) { dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length); nGlyphs = layoutChars(engine, (UniChar*)txtPtr, logicalStart, length, txtLen, - (dir == UBIDI_RTL), x, y, &status); + (dir == UBIDI_RTL), 0, 0, &status); getGlyphs(engine, glyphs, &status); getGlyphPositions(engine, positions, &status); @@ -1576,13 +1599,13 @@ measure_native_node(void* pNode, int use_glyph_metrics) for (i = 0; i < nGlyphs; ++i) { if (glyphs[i] < 0xfffe) { glyphIDs[realGlyphCount] = glyphs[i]; - locations[realGlyphCount].x = X2Fix(positions[2*i]); - locations[realGlyphCount].y = X2Fix(positions[2*i+1]); + locations[realGlyphCount].x = X2Fix(positions[2*i] + x); + locations[realGlyphCount].y = X2Fix(positions[2*i+1] + y); ++realGlyphCount; } } - x = positions[2*i]; - y = positions[2*i+1]; + x += positions[2*i]; + y += positions[2*i+1]; } wid = x; } @@ -2299,10 +2322,22 @@ open_dvi_output(FILE** fptr) if (*p++ == '\"') ++len; len += strlen(outputdriver); - len += 8; /* space for -o flag, quotes, NUL */ + if (output_directory) + len += strlen(output_directory); + len += 10; /* space for -o flag, quotes, NUL */ + for (p = (const char*)nameoffile+1; *p; p++) + if (*p == '\"') + ++len; /* allow extra space to escape quotes in filename */ cmd = xmalloc(len); strcpy(cmd, outputdriver); strcat(cmd, " -o \""); + if (output_directory) { + len = strlen(output_directory); + if (IS_DIR_SEP(output_directory[len-1])) + output_directory[len-1] = '\0'; + strcat(cmd, output_directory); + strcat(cmd, "/"); + } q = cmd + strlen(cmd); for (p = (const char*)nameoffile+1; *p; p++) { if (*p == '\"') @@ -2316,6 +2351,14 @@ open_dvi_output(FILE** fptr) free(cmd); cmd = cmd2; } + if (output_directory) { + char *fullname = concat3(output_directory, "/", nameoffile+1); + free(nameoffile); + namelength = strlen(fullname); + nameoffile = (char*)xmalloc(namelength+2); + strcpy(nameoffile+1, fullname); + free(fullname); + } *fptr = popen(cmd, "w"); free(cmd); return (*fptr != 0); diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h index 9e37b3ca63e..65b1db3a0e9 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h @@ -260,6 +260,7 @@ extern "C" { const char* getGlyphNamePtr(const char* buffer, int tableSize, UInt16 gid, int* len); + int countpdffilepages(); int find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page); int u_open_in(unicodefile* f, integer filefmt, const char* fopen_mode, integer mode, integer encodingData); int open_dvi_output(FILE** fptr); diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c index 4c64a65feb4..5228c669ab9 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c @@ -960,6 +960,31 @@ loadAATfont(ATSFontRef fontRef, long scaled_size, const char* cp1) return style; } +int +countpdffilepages() +{ + int rval = 0; + + char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1); + CFURLRef picFileURL = NULL; + if (pic_path) { + picFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)pic_path, strlen(pic_path), false); + if (picFileURL != NULL) { + FSRef picFileRef; + CFURLGetFSRef(picFileURL, &picFileRef); + CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(picFileURL); + if (document != NULL) { + rval = CGPDFDocumentGetNumberOfPages(document); + CGPDFDocumentRelease(document); + } + CFRelease(picFileURL); + } + free(pic_path); + } + + return rval; +} + int find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) { diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_pic.c b/Build/source/texk/web2c/xetexdir/XeTeX_pic.c index a511b848038..9491e9d1a8a 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_pic.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_pic.c @@ -32,6 +32,22 @@ XeTeX_pic.c #include "jpegimage.h" #include "bmpimage.h" + +int +countpdffilepages() +{ + int rval = 0; + + char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1); + if (pic_path) { + rval = pdf_count_pages(pic_path); + free(pic_path); + } + + return rval; +} + + /* locate picture file from /nameoffile+1/ using kpathsearch pdfBoxType indicates which pdf bounding box to use (0 for \XeTeXpicfile) diff --git a/Build/source/texk/web2c/xetexdir/appleGlyphNames.c b/Build/source/texk/web2c/xetexdir/appleGlyphNames.c index 21fe6cc6719..a036fb9c393 100644 --- a/Build/source/texk/web2c/xetexdir/appleGlyphNames.c +++ b/Build/source/texk/web2c/xetexdir/appleGlyphNames.c @@ -28,7 +28,7 @@ use or other dealings in this Software without prior written authorization from SIL International. \****************************************************************************/ -char* appleGlyphNames[] = { +const char* appleGlyphNames[] = { ".notdef", ".null", "nonmarkingreturn", diff --git a/Build/source/texk/web2c/xetexdir/pdfimage.cpp b/Build/source/texk/web2c/xetexdir/pdfimage.cpp index 21af77c6572..2c60d09c790 100644 --- a/Build/source/texk/web2c/xetexdir/pdfimage.cpp +++ b/Build/source/texk/web2c/xetexdir/pdfimage.cpp @@ -82,3 +82,25 @@ pdf_get_rect(char* filename, int page_num, int pdf_box, realrect* box) return 0; } + +int +pdf_count_pages(char* filename) +{ + int pages = 0; + GString* name = new GString(filename); + PDFDoc* doc = new PDFDoc(name); + + if (!doc) { + delete name; + return 0; + } + + /* if the doc got created, it now owns name, so we mustn't delete it! */ + + if (doc->isOk()) + pages = doc->getNumPages(); + + delete doc; + + return pages; +} diff --git a/Build/source/texk/web2c/xetexdir/pdfimage.h b/Build/source/texk/web2c/xetexdir/pdfimage.h index 0869c03aa1e..b2a77d9f311 100644 --- a/Build/source/texk/web2c/xetexdir/pdfimage.h +++ b/Build/source/texk/web2c/xetexdir/pdfimage.h @@ -20,6 +20,8 @@ extern "C" { extern int pdf_get_rect(char* filename, int page_num, int pdf_box, realrect* box); +extern int pdf_count_pages(char* filename); + #ifdef __cplusplus }; #endif diff --git a/Build/source/texk/web2c/xetexdir/pool2c.pl b/Build/source/texk/web2c/xetexdir/pool2c.pl new file mode 100644 index 00000000000..c2628deab46 --- /dev/null +++ b/Build/source/texk/web2c/xetexdir/pool2c.pl @@ -0,0 +1,74 @@ +#! /usr/bin/perl + +# Convert web .pool file into C source +# Result is an array of chars (bytes) containing the strings, +# each prefixed by a length byte. +# The function initpool() loads this data into TeX's pool. + +# usage: perl pool2c.pl NAME.pool +# writes output to ${NAME}_pool.c if only one arg provided + +die "expected pool name as argument" unless $#ARGV >= 0; +die "too many arguments" if $#ARGV > 1; + +$prog = `basename $ARGV[0] .pool`; +chomp($prog); + +$outfile = ($#ARGV == 1) ? $ARGV[1] : "${prog}_pool.c"; + +open IN, "< $ARGV[0]" or die "can't open input $ARGV[0]"; +open OUT, "> $outfile" or die "can't open output $outfile"; + +print OUT <<__EOT__; +/* This file is auto-generated from $ARGV[0] by pool2c.pl */ +#define EXTERN extern +#include "${prog}d.h" + +#include + +static unsigned char POOL[] = +__EOT__ +$pool_len = 0; +while () { + chomp; + if (m/^([0-9]{2})(.*)$/) { + ($len, $str) = ($1, $2); + if (length($str) != $len) { + die "*** pool string length error:\n$_\n"; + } + $str =~ s/(["\\])/\\$1/g; + $str =~ s/\?\?\?/\\?\\?\\?/g; + printf OUT "\t\"\\x%02X\" \"%s\"\n", $len, $str; + $pool_len += $len + 1; + } + elsif (m/^\*[0-9]+$/) { + last; + } + else { + die "*** unexpected line in pool file:\n$_\n"; + } +} + +close IN; + +print OUT <<__EOT__; + ; + +#define POOL_LEN $pool_len + +int initpool(int limit) { + int g = 0; + unsigned char *s = POOL; + while (s < POOL + POOL_LEN) { + int len = *s++; + if (poolptr + len >= limit) + return 0; + while (len-- > 0) + strpool[poolptr++] = *s++; + g = makestring(); + } + return g; +} +__EOT__ + +close OUT; diff --git a/Build/source/texk/web2c/xetexdir/xetex-new.ch b/Build/source/texk/web2c/xetexdir/xetex-new.ch index 5340b3fe061..07adba9e228 100644 --- a/Build/source/texk/web2c/xetexdir/xetex-new.ch +++ b/Build/source/texk/web2c/xetexdir/xetex-new.ch @@ -1,6 +1,6 @@ % /****************************************************************************\ % Part of the XeTeX typesetting system -% copyright (c) 1994-2006 by SIL International +% copyright (c) 1994-2008 by SIL International % written by Jonathan Kew % % Permission is hereby granted, free of charge, to any person obtaining @@ -55,8 +55,8 @@ @d eTeX_version_string=='-2.2' {current \eTeX\ version} @d XeTeX_version=0 -@d XeTeX_revision==".996" -@d XeTeX_version_string=='-0.996-patch1' {current \XeTeX\ version} +@d XeTeX_revision==".996-patch2" +@d XeTeX_version_string=='-0.996-patch2' {current \XeTeX\ version} @z @x @@ -346,41 +346,80 @@ end @z @x -name_of_file := xmalloc_array (ASCII_code, name_length + 1); -@y -name_of_file := xmalloc_array (UTF8_code, name_length + 1); -@z +@ When the \.{WEB} system program called \.{TANGLE} processes the \.{TEX.WEB} +description that you are now reading, it outputs the \PASCAL\ program +\.{TEX.PAS} and also a string pool file called \.{TEX.POOL}. The \.{INITEX} +@.WEB@>@.INITEX@> +program reads the latter file, where each string appears as a two-digit decimal +length followed by the string itself, and the information is recorded in +\TeX's string memory. -@x +@= +@!init @!pool_file:alpha_file; {the string-pool file output by \.{TANGLE}} +tini + +@ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#); + a_close(pool_file); get_strings_started:=false; return; + end +@= +name_length := strlen (pool_name); +name_of_file := xmalloc_array (ASCII_code, name_length + 1); +strcpy (stringcast(name_of_file+1), pool_name); {copy the string} +if a_open_in (pool_file, kpse_texpool_format) then + begin c:=false; + repeat @; + until c; + a_close(pool_file); get_strings_started:=true; + end +else bad_pool('! I can''t read ', pool_name, '; bad path?') +@.I can't read TEX.POOL@> + +@ @= +begin if eof(pool_file) then bad_pool('! ', pool_name, ' has no check sum.'); +@.TEX.POOL has no check sum@> +read(pool_file,m); read(pool_file,n); {read two digits of string length} +if m='*' then @ else begin if (xord[m]<"0")or(xord[m]>"9")or@| (xord[n]<"0")or(xord[n]>"9") then -@y -else begin if (m<"0")or(m>"9")or@| - (n<"0")or(n>"9") then -@z - -@x + bad_pool('! ', pool_name, ' line doesn''t begin with two digits.'); +@.TEX.POOL line doesn't...@> l:=xord[m]*10+xord[n]-"0"*11; {compute the length} -@y - l:=m*10+n-"0"*11; {compute the length} -@z - -@x + if pool_ptr+l+string_vacancies>pool_size then + bad_pool('! You have to increase POOLSIZE.'); +@.You have to increase POOLSIZE@> + for k:=1 to l do + begin if eoln(pool_file) then m:=' '@+else read(pool_file,m); append_char(xord[m]); -@y - append_char(m); -@z + end; + read_ln(pool_file); g:=make_string; + end; +end -@x -loop@+ begin if (xord[n]<"0")or(xord[n]>"9") then -@y -loop@+ begin if (n<"0")or(n>"9") then -@z +@ The \.{WEB} operation \.{@@\$} denotes the value that should be at the +end of this \.{TEX.POOL} file; any other value means that the wrong pool +file has been loaded. +@^check sum@> -@x +@= +begin a:=0; k:=1; +loop@+ begin if (xord[n]<"0")or(xord[n]>"9") then + bad_pool('! ', pool_name, ' check sum doesn''t have nine digits.'); +@.TEX.POOL check sum...@> a:=10*a+xord[n]-"0"; + if k=9 then goto done; + incr(k); read(pool_file,n); + end; +done: if a<>@$ then + bad_pool('! ', pool_name, ' doesn''t match; tangle me again (or fix the path).'); +@.TEX.POOL doesn't match@> +c:=true; +end @y - a:=10*a+n-"0"; +@ @= +if init_pool(pool_size-string_vacancies) = 0 then + get_strings_started:=false; +get_strings_started:=true; @z @x @@ -501,11 +540,23 @@ end else begin end; exit:end; +@ @d native_room(#)==while native_text_size <= native_len+# do begin + native_text_size:=native_text_size+128; + native_text:=xrealloc(native_text, native_text_size * sizeof(UTF16_code)); + end +@d append_native(#)==begin native_text[native_len]:=#; incr(native_len); end + @ @= -doing_special: boolean; +@!doing_special: boolean; +@!native_text: ^UTF16_code; { buffer for collecting native-font strings } +@!native_text_size: integer; { size of buffer } +@!native_len: integer; +@!save_native_len: integer; @ @= doing_special:=false; +native_text_size:=128; +native_text:=xmalloc(native_text_size * sizeof(UTF16_code)); @z @x @@ -710,8 +761,7 @@ and then a word containing a size field for the node, a font number, a length, a Then there is a field containing a C pointer to a glyph info array; this and the glyph count are set by |set_native_metrics|. Copying and freeing of these nodes needs to take account of this! -This is followed by |length| bytes, for the actual characters of the string. -(Yes, we count in bytes, even though what we store there is UTF-16.) +This is followed by |2*length| bytes, for the actual characters of the string (in UTF-16). So |native_node_size|, which does not include any space for the actual text, is 6.} @@ -1142,9 +1192,10 @@ else begin print_esc("scriptscriptfont"); @d eTeX_state_code=etex_int_base+9 {\eTeX\ state variables} @d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters} @y -@d XeTeX_linebreak_locale_code=etex_int_base+9 {string number of locale to use for linebreak locations} -@d XeTeX_linebreak_penalty_code=etex_int_base+10 {penalty to use at locale-dependent linebreak locations} -@d eTeX_state_code=etex_int_base+11 {\eTeX\ state variables} +@d suppress_fontnotfound_error_code=etex_int_base+9 {suppress errors for missing fonts} +@d XeTeX_linebreak_locale_code=etex_int_base+10 {string number of locale to use for linebreak locations} +@d XeTeX_linebreak_penalty_code=etex_int_base+11 {penalty to use at locale-dependent linebreak locations} +@d eTeX_state_code=etex_int_base+12 {\eTeX\ state variables} @d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters} @z @@ -1162,6 +1213,7 @@ else begin print_esc("scriptscriptfont"); @d saving_hyph_codes==int_par(saving_hyph_codes_code) @y @d saving_hyph_codes==int_par(saving_hyph_codes_code) +@d suppress_fontnotfound_error==int_par(suppress_fontnotfound_error_code) @d XeTeX_linebreak_locale==int_par(XeTeX_linebreak_locale_code) @d XeTeX_linebreak_penalty==int_par(XeTeX_linebreak_penalty_code) @z @@ -1805,7 +1857,7 @@ end @# @d XeTeX_int=eTeX_int+8 {first of \XeTeX\ codes for integers} @# -@d eTeX_dim=XeTeX_int+29 {first of \eTeX\ codes for dimensions} +@d eTeX_dim=XeTeX_int+30 {first of \eTeX\ codes for dimensions} {changed for \XeTeX\ to make room for \XeTeX\ integers} @z @@ -2536,6 +2588,7 @@ loop@+begin if (cur_cmd>other_char)or(cur_chr>biggest_char) then @!loaded_font_mapping: void_pointer; { used by load_native_font to return mapping, if any } @!loaded_font_flags: char; { used by load_native_font to return flags } @!loaded_font_letter_space: scaled; +@!loaded_font_design_size: scaled; @!mapped_text: ^UTF16_code; { scratch buffer used while applying font mappings } @!xdv_buffer: ^char; { scratch buffer used in generating XDV output } @z @@ -2548,9 +2601,9 @@ pack_file_name(nom,aire,cur_ext); if quoted_filename then begin { quoted name, so try for a native font } g:=load_native_font(u,nom,aire,s); - if g=null_font then goto bad_tfm else goto done; + if g<>null_font then goto done; end; -{ it was an unquoted name, so try for a TFM file } +{ it was an unquoted name, or not found as an installed font, so try for a TFM file } @; @y if g<>null_font then goto done; -if file_name_quote_char=0 then begin +if not quoted_filename then begin { we failed to find a TFM file, so try for a native font } g:=load_native_font(u,nom,aire,s); if g<>null_font then goto done end; bad_tfm: -if (not file_opened) and (file_name_quote_char<>0) then begin - @; -end; -@; +if suppress_fontnotfound_error=0 then begin + @; + end; @z @x @@ -2593,17 +2645,6 @@ else print(" not loadable: Metric (TFM) file or installed font not found"); @ @= @; @y -@ @= -start_font_error_message; -@.Font x=xx not loadable...@> -print(" not loadable: installed font not found"); -help4("I wasn't able to find this font in the Mac OS,")@/ -("so I will ignore the font specification.")@/ -("You might try inserting a different font spec;")@/ -("e.g., type `I\font='."); -error; -goto done - @ @= @; @z @@ -2945,21 +2986,22 @@ while (q <> null) and (not is_char_node(q)) and (type(q) = disc_node) do dvi_four(last_bop); last_bop:=page_loc; @y dvi_four(last_bop); last_bop:=page_loc; +{ generate a pagesize \special at start of page } +old_setting:=selector; selector:=new_string; +print("pdf:pagesize "); if (pdf_page_width > 0) and (pdf_page_height > 0) then begin - { generate a papersize \special at start of page } - old_setting:=selector; selector:=new_string; - print("papersize "); - if mag=1000 then print_scaled(pdf_page_width) - else print_scaled(xn_over_d(pdf_page_width,mag,1000)); - print("pt"); print(","); - if mag=1000 then print_scaled(pdf_page_height) - else print_scaled(xn_over_d(pdf_page_height,mag,1000)); + print("width"); print(" "); + print_scaled(pdf_page_width); + print("pt"); print(" "); + print("height"); print(" "); + print_scaled(pdf_page_height); print("pt"); - selector:=old_setting; - dvi_out(xxx1); dvi_out(cur_length); - for s:=str_start_macro(str_ptr) to pool_ptr-1 do dvi_out(so(str_pool[s])); - pool_ptr:=str_start_macro(str_ptr); {erase the string} -end; +end else + print("default"); +selector:=old_setting; +dvi_out(xxx1); dvi_out(cur_length); +for s:=str_start_macro(str_ptr) to pool_ptr-1 do dvi_out(so(str_pool[s])); +pool_ptr:=str_start_macro(str_ptr); {erase the string} @z @x @@ -3786,27 +3828,27 @@ hmode+char_num: begin scan_usv_num; cur_chr:=cur_val; goto main_loop;@+end; @x adjust_space_factor;@/ @y - { added code for native font support } if is_native_font(cur_font) then begin if mode>0 then if language<>clang then fix_language; main_h := 0; main_f := cur_font; - + native_len := 0; + collect_native: adjust_space_factor; if (cur_chr > @"FFFF) then begin - str_room(2); - append_char((cur_chr - @"10000) div 1024 + @"D800); - append_char((cur_chr - @"10000) mod 1024 + @"DC00); + native_room(2); + append_native((cur_chr - @"10000) div 1024 + @"D800); + append_native((cur_chr - @"10000) mod 1024 + @"DC00); end else begin - str_room(1); - append_char(cur_chr); + native_room(1); + append_native(cur_chr); end; is_hyph := (cur_chr = hyphen_char[main_f]) or (XeTeX_dash_break_en and (cur_chr = @"2014) or (cur_chr = @"2013)); - if (main_h = 0) and is_hyph then main_h := cur_length; + if (main_h = 0) and is_hyph then main_h := native_len; {try to collect as many chars as possible in the same font} get_next; @@ -3820,27 +3862,26 @@ collect_native: end; if (font_mapping[main_f] <> 0) then begin - main_k := apply_mapping(font_mapping[main_f], address_of(str_pool[str_start_macro(str_ptr)]), cur_length); - pool_ptr := str_start_macro(str_ptr); { flush the string, as we'll be using the mapped text instead } - str_room(main_k); + main_k := apply_mapping(font_mapping[main_f], native_text, native_len); + native_len := 0; + native_room(main_k); main_h := 0; for main_p := 0 to main_k - 1 do begin - append_char(mapped_text[main_p]); + append_native(mapped_text[main_p]); if (main_h = 0) and ((mapped_text[main_p] = hyphen_char[main_f]) or (XeTeX_dash_break_en and ((mapped_text[main_p] = @"2014) or (mapped_text[main_p] = @"2013)) ) ) - then main_h := cur_length; + then main_h := native_len; end end; if tracing_lost_chars > 0 then begin - temp_ptr := str_start_macro(str_ptr); - main_p := temp_ptr + cur_length; - while (temp_ptr < main_p) do begin - main_k := str_pool[temp_ptr]; + temp_ptr := 0; + while (temp_ptr < native_len) do begin + main_k := native_text[temp_ptr]; incr(temp_ptr); if (main_k >= @"D800) and (main_k < @"DC00) then begin main_k := @"10000 + (main_k - @"D800) * 1024; - main_k := main_k + str_pool[temp_ptr] - @"DC00; + main_k := main_k + native_text[temp_ptr] - @"DC00; incr(temp_ptr); end; if map_char_to_glyph(main_f, main_k) = 0 then @@ -3848,48 +3889,54 @@ collect_native: end end; - main_k := cur_length; + main_k := native_len; main_pp := tail; if mode=hmode then begin main_ppp := head; - if main_ppp<>main_pp then - while (link(main_ppp)<>main_pp) do - main_ppp:=link(main_ppp); { find node preceding tail } + if main_ppp<>main_pp then { find node preceding tail, skipping discretionaries } + while (link(main_ppp)<>main_pp) do begin + if (not is_char_node(main_ppp)) and (type(main_ppp=disc_node)) then begin + temp_ptr:=main_ppp; + for main_p:=1 to replace_count(temp_ptr) do main_ppp:=link(main_ppp); + end; + if main_ppp<>main_pp then main_ppp:=link(main_ppp); + end; - temp_ptr := str_start_macro(str_ptr); + temp_ptr := 0; repeat if main_h = 0 then main_h := main_k; - if (not is_char_node(main_pp)) + if (not is_char_node(main_pp)) and (type(main_pp)=whatsit_node) and (subtype(main_pp)=native_word_node) and (native_font(main_pp)=main_f) and (main_ppp<>main_pp) - and type(main_ppp)<>disc_node + and (not is_char_node(main_ppp)) + and (type(main_ppp)<>disc_node) then begin { make a new temp string that contains the concatenated text of |tail| + the current word/fragment } main_k := main_h + native_length(main_pp); - str_room(main_k); + native_room(main_k); - temp_ptr := pool_ptr; + save_native_len := native_len; for main_p := 0 to native_length(main_pp) - 1 do - append_char(get_native_char(main_pp, main_p)); - for main_p := str_start_macro(str_ptr) to temp_ptr - 1 do - append_char(str_pool[main_p]); + append_native(get_native_char(main_pp, main_p)); + for main_p := 0 to main_h - 1 do + append_native(native_text[temp_ptr + main_p]); - do_locale_linebreaks(temp_ptr, main_k); + do_locale_linebreaks(save_native_len, main_k); - pool_ptr := temp_ptr; { discard the temp string } - main_k := cur_length - main_h; { and set main_k to remaining length of new word } - temp_ptr := str_start_macro(str_ptr) + main_h; { pointer to remaining fragment } + native_len := save_native_len; { discard the temp string } + main_k := native_len - main_h - temp_ptr; { and set main_k to remaining length of new word } + temp_ptr := main_h; { pointer to remaining fragment } main_h := 0; - while (main_h < main_k) and (str_pool[temp_ptr + main_h] <> hyphen_char[main_f]) + while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f]) and ( (not XeTeX_dash_break_en) - or ((str_pool[temp_ptr + main_h] <> @"2014) and (str_pool[temp_ptr + main_h] <> @"2013)) ) + or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) ) do incr(main_h); { look for next hyphen or end of text } if (main_h < main_k) then incr(main_h); @@ -3909,9 +3956,9 @@ collect_native: main_k := main_k - main_h; { decrement remaining length } main_h := 0; - while (main_h < main_k) and (str_pool[temp_ptr + main_h] <> hyphen_char[main_f]) + while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f]) and ( (not XeTeX_dash_break_en) - or ((str_pool[temp_ptr + main_h] <> @"2014) and (str_pool[temp_ptr + main_h] <> @"2013)) ) + or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) ) do incr(main_h); { look for next hyphen or end of text } if (main_h < main_k) then incr(main_h); @@ -3920,6 +3967,7 @@ collect_native: if (main_k > 0) or is_hyph then begin tail_append(new_disc); { add a break if we aren't at end of text (must be a hyphen), or if last char in original text was a hyphen } + main_pp:=tail; end; until main_k = 0; @@ -3935,7 +3983,7 @@ collect_native: set_native_char(tail, main_p, get_native_char(main_pp, main_p)); { append the new text } for main_p := 0 to main_k - 1 do - set_native_char(tail, main_p + native_length(main_pp), str_pool[str_start_macro(str_ptr) + main_p]); + set_native_char(tail, main_p + native_length(main_pp), native_text[main_p]); set_native_metrics(tail, XeTeX_use_glyph_metrics); { remove the preceding node from the list } @@ -3951,12 +3999,11 @@ collect_native: link(main_pp) := new_native_word_node(main_f, main_k); tail := link(main_pp); for main_p := 0 to main_k - 1 do - set_native_char(tail, main_p, str_pool[str_start_macro(str_ptr) + main_p]); + set_native_char(tail, main_p, native_text[main_p]); set_native_metrics(tail, XeTeX_use_glyph_metrics); end end; - pool_ptr := str_start_macro(str_ptr); goto reswitch; end; { End of added code for native fonts } @@ -5004,16 +5051,39 @@ end else @x @ @d adv_past(#)==@+if subtype(#)=language_node then - begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end + begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#); + set_hyph_index; + end + +@=@+ +adv_past(cur_p) @y -@ @d adv_past(#)==@+if subtype(#)=language_node then - begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end +@ @d adv_past_linebreak(#)==@+if subtype(#)=language_node then + begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#); + set_hyph_index; + end else if (subtype(#)=native_word_node) or (subtype(#)=glyph_node) or (subtype(#)=pic_node) or (subtype(#)=pdf_node) then begin act_width:=act_width+width(#); end + +@=@+ +adv_past_linebreak(cur_p) +@z + +@x +@ @=@+ +adv_past(s) +@y +@ @d adv_past_prehyph(#)==@+if subtype(#)=language_node then + begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#); + set_hyph_index; + end + +@=@+ +adv_past_prehyph(s) @z @x @@ -5565,6 +5635,8 @@ end @d pdf_last_x_pos_code = XeTeX_int+27 @d pdf_last_y_pos_code = XeTeX_int+28 +@d XeTeX_pdf_page_count_code = XeTeX_int+29 + { NB: must update eTeX_dim when items are added here! } @z @@ -5619,6 +5691,8 @@ 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); + +primitive("XeTeXpdfpagecount",last_item,XeTeX_pdf_page_count_code); @z @x @@ -5662,6 +5736,8 @@ XeTeX_last_char_code: print_esc("XeTeXlastfontchar"); pdf_last_x_pos_code: print_esc("pdflastxpos"); pdf_last_y_pos_code: print_esc("pdflastypos"); + +XeTeX_pdf_page_count_code: print_esc("XeTeXpdfpagecount"); @z @x @@ -5835,6 +5911,12 @@ XeTeX_first_char_code,XeTeX_last_char_code: pdf_last_x_pos_code: cur_val := pdf_last_x_pos; pdf_last_y_pos_code: cur_val := pdf_last_y_pos; +XeTeX_pdf_page_count_code: + begin + scan_and_pack_name; + cur_val:=count_pdf_file_pages; + end; + @ Slip in an extra procedure here and there.... @= @@ -5984,6 +6066,7 @@ font_char_ic_code: begin scan_font_ident; q:=cur_val; scan_usv_num; @x eTeX_state_code+TeXXeT_code:print_esc("TeXXeTstate"); @y +suppress_fontnotfound_error_code:print_esc("suppressfontnotfounderror"); eTeX_state_code+TeXXeT_code:print_esc("TeXXeTstate"); eTeX_state_code+XeTeX_dash_break_code:print_esc("XeTeXdashbreakstate"); @z @@ -6255,10 +6338,18 @@ begin load_native_font := null_font; - if (s < 0) then actual_size := -s * unity div 100 else actual_size := s; - font_engine := find_native_font(name_of_file + 1, actual_size); + font_engine := find_native_font(name_of_file + 1, s); if font_engine = 0 then goto done; + if s>=0 then + actual_size := s + else begin + if (s <> -1000) then + actual_size := xn_over_d(loaded_font_design_size,-s,1000) + else + actual_size := loaded_font_design_size; + end; + { look again to see if the font is already loaded, now that we know its canonical name } str_room(name_length); for k := 1 to name_length do @@ -6289,7 +6380,7 @@ begin font_check[font_ptr].b2 := 0; font_check[font_ptr].b3 := 0; font_glue[font_ptr] := null; - font_dsize[font_ptr] := 10 * unity; + font_dsize[font_ptr] := loaded_font_design_size; font_size[font_ptr] := actual_size; if (native_font_type_flag = aat_font_flag) then begin @@ -6344,7 +6435,7 @@ begin done: end; -procedure do_locale_linebreaks(s: pointer; len: integer); +procedure do_locale_linebreaks(s: integer; len: integer); var offs, prevOffs, i: integer; use_penalty, use_skip: boolean; @@ -6353,12 +6444,12 @@ begin link(tail) := new_native_word_node(main_f, len); tail := link(tail); for i := 0 to len - 1 do - set_native_char(tail, i, str_pool[s + i]); + set_native_char(tail, i, native_text[s + i]); set_native_metrics(tail, XeTeX_use_glyph_metrics); end else begin use_skip := XeTeX_linebreak_skip <> zero_glue; use_penalty := XeTeX_linebreak_penalty <> 0 or not use_skip; - linebreak_start(XeTeX_linebreak_locale, address_of(str_pool[s]), len); + linebreak_start(XeTeX_linebreak_locale, native_text + s, len); offs := 0; repeat prevOffs := offs; @@ -6373,7 +6464,7 @@ begin link(tail) := new_native_word_node(main_f, offs - prevOffs); tail := link(tail); for i := prevOffs to offs - 1 do - set_native_char(tail, i - prevOffs, str_pool[s + i]); + set_native_char(tail, i - prevOffs, native_text[s + i]); set_native_metrics(tail, XeTeX_use_glyph_metrics); end; until offs < 0; diff --git a/Build/source/texk/web2c/xetexdir/xetex.defines b/Build/source/texk/web2c/xetexdir/xetex.defines index 218d8228c97..11d03e5ecd2 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.defines +++ b/Build/source/texk/web2c/xetexdir/xetex.defines @@ -61,6 +61,7 @@ authorization from SIL International. @define procedure printutf8str(); @define procedure setinputfileencoding(); @define procedure terminatefontmanager; +@define function initpool(); @define procedure memcpy(); @define function casttoptr(); @@ -133,6 +134,7 @@ authorization from SIL International. @define function findpicfile(); @define function picpathbyte(); +@define function countpdffilepages; @define procedure makeidentity(); @define procedure makescale(); diff --git a/Build/source/texk/web2c/xetexdir/xetex.mk b/Build/source/texk/web2c/xetexdir/xetex.mk index 0c54f08a093..621bd99a629 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.mk +++ b/Build/source/texk/web2c/xetexdir/xetex.mk @@ -108,10 +108,16 @@ xetexdir/xetex.version: $(srcdir)/xetexdir/xetex-new.ch grep '^@d XeTeX_version_string==' $(srcdir)/xetexdir/xetex-new.ch \ | sed "s/^.*'-//;s/'.*$$//" >xetexdir/xetex.version +# Extract etex version +xetexdir/etex.version: $(srcdir)/etexdir/etex.ch + test -d xetexdir || mkdir xetexdir + grep '^@d eTeX_version_string==' $(srcdir)/etexdir/etex.ch \ + | sed "s/^.*'-//;s/'.*$$//" >xetexdir/etex.version + # The C sources. xetex_c = xetexini.c xetex0.c xetex1.c xetex2.c xetex_o = xetexini.o xetex0.o xetex1.o xetex2.o xetexextra.o -xetex_add_o = trans.o XeTeX_ext.o $(xetex_platform_o) +xetex_add_o = trans.o XeTeX_ext.o xetex_pool.o $(xetex_platform_o) # these compilations require the path to TECkit headers; # just setting it in XCFLAGS doesn't seem to work when we're called @@ -126,6 +132,8 @@ xetex2.o: xetex2.c $(srcdir)/xetexdir/XeTeX_ext.h $(compile) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@ xetexextra.o: xetexextra.c $(srcdir)/xetexdir/XeTeX_ext.h $(compile) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@ +xetex_pool.o: xetex_pool.c $(srcdir)/xetexdir/XeTeX_ext.h + $(compile) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@ # image support mfileio.o: $(srcdir)/xetexdir/mfileio.c $(srcdir)/xetexdir/mfileio.h @@ -205,11 +213,15 @@ $(xetex_c) xetexcoerce.h xetexd.h: xetex.p $(web2c_texmf) $(web2c) xetex xetexextra.c: lib/texmfmp.c xetexdir/xetexextra.h sed s/TEX-OR-MF-OR-MP/xetex/ $(srcdir)/lib/texmfmp.c >$@ -xetexdir/xetexextra.h: xetexdir/xetexextra.in xetexdir/xetex.version +xetexdir/xetexextra.h: xetexdir/xetexextra.in xetexdir/xetex.version xetexdir/etex.version test -d xetexdir || mkdir xetexdir - sed s/XETEX-VERSION/`cat xetexdir/xetex.version`/ \ + sed -e s/XETEX-VERSION/`cat xetexdir/xetex.version`/ \ + -e s/ETEX-VERSION/`cat xetexdir/etex.version`/ \ $(srcdir)/xetexdir/xetexextra.in >$@ +xetex_pool.c: xetex.pool + perl $(srcdir)/xetexdir/pool2c.pl $< $@ + # Tangling xetex.p xetex.pool: ./otangle xetex.web # xetex.ch ./otangle xetex.web # xetex.ch @@ -258,7 +270,7 @@ xetex.web: tie xetexdir/xetex.mk $(xetex_web_srcs) clean:: xetex-clean xetex-clean: # etrip-clean $(LIBTOOL) --mode=clean $(RM) xetex - rm -f $(xetex_o) $(xetex_c) xetexextra.c xetexcoerce.h xetexd.h + rm -f $(xetex_o) $(xetex_c) xetexextra.c xetex_pool.c xetexcoerce.h xetexd.h rm -f xetexdir/xetexextra.h xetexdir/xetex.version rm -f xetex.p xetex.pool xetex.web xetex.ch rm -f xetex.fmt xetex.log @@ -289,7 +301,7 @@ xelatex.fmt: xetex # Install install-xetex: install-xetex-exec install-xetex-data install-xetex-exec: install-xetex-programs install-xetex-links -install-xetex-data: install-xetex-pool @FMU@ install-xetex-dumps +install-xetex-data: @FMU@ install-xetex-dumps install-xetex-dumps: install-xetex-fmts install-programs: @XETEX@ install-xetex-programs @@ -310,7 +322,5 @@ install-xetex-fmts: xefmts $(xefmtdir) (cd ${DESTDIR}$(bindir) && (rm -f $$base; $(LN) xetex $$base)); done install-data:: @XETEX@ install-xetex-data -install-xetex-pool: xetex.pool $(texpooldir) - $(INSTALL_DATA) xetex.pool ${DESTDIR}$(texpooldir)/xetex.pool # end of xetex.mk diff --git a/Build/source/texk/web2c/xetexdir/xetexextra.in b/Build/source/texk/web2c/xetexdir/xetexextra.in index 9286d98fe37..e9e883ab3b7 100644 --- a/Build/source/texk/web2c/xetexdir/xetexextra.in +++ b/Build/source/texk/web2c/xetexdir/xetexextra.in @@ -51,7 +51,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define BANNER "This is XeTeX, Version 3.141592-XETEX-VERSION" +#define BANNER "This is XeTeX, Version 3.141592-ETEX-VERSION-XETEX-VERSION" #define COPYRIGHT_HOLDER "SIL International" #define AUTHOR "Jonathan Kew" #define PROGRAM_HELP XETEXHELP -- cgit v1.2.3