summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp')
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp661
1 files changed, 661 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
new file mode 100644
index 00000000000..11094b10b47
--- /dev/null
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
@@ -0,0 +1,661 @@
+/****************************************************************************\
+ Part of the XeTeX typesetting system
+ Copyright (c) 1994-2008 by SIL International
+ Copyright (c) 2009-2014 by Jonathan Kew
+
+ SIL Author(s): Jonathan Kew
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"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 THE COPYRIGHT HOLDERS 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 the copyright holders
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written
+authorization from the copyright holders.
+\****************************************************************************/
+
+#include <w2c/config.h>
+
+#include "XeTeX_web.h"
+
+#ifdef XETEX_MAC
+#include "XeTeXFontMgr_Mac.h"
+#else
+#include "XeTeXFontMgr_FC.h"
+#endif
+#include "XeTeXFontInst.h"
+
+#include <hb-ot.h>
+
+// see cpascal.h
+#define printcstring(STR) \
+ do { \
+ const char* ch_ptr = (STR); \
+ while (*ch_ptr) \
+ zprintchar(*(ch_ptr++)); \
+ } while (0)
+
+XeTeXFontMgr* XeTeXFontMgr::sFontManager = NULL;
+char XeTeXFontMgr::sReqEngine = 0;
+
+/* use our own fmax function because it seems to be missing on certain platforms
+ (solaris2.9, at least) */
+static inline double
+my_fmax(double x, double y)
+{
+ return (x > y) ? x : y;
+}
+
+XeTeXFontMgr*
+XeTeXFontMgr::GetFontManager()
+{
+ if (sFontManager == NULL) {
+#ifdef XETEX_MAC
+ sFontManager = new XeTeXFontMgr_Mac;
+#else
+ sFontManager = new XeTeXFontMgr_FC;
+#endif
+ sFontManager->initialize();
+ }
+
+ return sFontManager;
+}
+
+void
+XeTeXFontMgr::Terminate()
+{
+ if (sFontManager != NULL) {
+ sFontManager->terminate();
+ // we don't actually deallocate the manager, just ask it to clean up
+ // any auxiliary data such as the cocoa pool or freetype/fontconfig stuff
+ // as we still need to access font names after this is called
+ }
+}
+
+PlatformFontRef
+XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
+ // 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;
+ double dsize = 10.0;
+ loadedfontdesignsize = 655360L;
+
+ for (int pass = 0; pass < 2; ++pass) {
+ // try full name as given
+ std::map<std::string,Font*>::iterator i = m_nameToFont.find(nameStr);
+ if (i != m_nameToFont.end()) {
+ font = i->second;
+ if (font->opSizeInfo.designSize != 0.0)
+ dsize = font->opSizeInfo.designSize;
+ break;
+ }
+
+ // if there's a hyphen, split there and try Family-Style
+ int hyph = nameStr.find('-');
+ if (hyph > 0 && hyph < nameStr.length() - 1) {
+ std::string family(nameStr.begin(), nameStr.begin() + hyph);
+ std::map<std::string,Family*>::iterator f = m_nameToFamily.find(family);
+ if (f != m_nameToFamily.end()) {
+ std::string style(nameStr.begin() + hyph + 1, nameStr.end());
+ i = f->second->styles->find(style);
+ if (i != f->second->styles->end()) {
+ font = i->second;
+ if (font->opSizeInfo.designSize != 0.0)
+ dsize = font->opSizeInfo.designSize;
+ break;
+ }
+ }
+ }
+
+ // try as PostScript name
+ i = m_psNameToFont.find(nameStr);
+ if (i != m_psNameToFont.end()) {
+ font = i->second;
+ if (font->opSizeInfo.designSize != 0.0)
+ dsize = font->opSizeInfo.designSize;
+ break;
+ }
+
+ // try for the name as a family name
+ std::map<std::string,Family*>::iterator f = m_nameToFamily.find(nameStr);
+
+ if (f != m_nameToFamily.end()) {
+ // look for a family member with the "regular" bit set in OS/2
+ int regFonts = 0;
+ for (i = f->second->styles->begin(); i != f->second->styles->end(); ++i)
+ if (i->second->isReg) {
+ if (regFonts == 0)
+ font = i->second;
+ ++regFonts;
+ }
+
+ // families with Ornament or similar fonts may flag those as Regular,
+ // which confuses the search above... so try some known names
+ if (font == NULL || regFonts > 1) {
+ // try for style "Regular", "Plain", "Normal", "Roman"
+ i = f->second->styles->find("Regular");
+ if (i != f->second->styles->end())
+ font = i->second;
+ else {
+ i = f->second->styles->find("Plain");
+ if (i != f->second->styles->end())
+ font = i->second;
+ else {
+ i = f->second->styles->find("Normal");
+ if (i != f->second->styles->end())
+ font = i->second;
+ else {
+ i = f->second->styles->find("Roman");
+ if (i != f->second->styles->end())
+ font = i->second;
+ }
+ }
+ }
+ }
+
+ if (font == NULL) {
+ // look through the family for the (weight, width, slant) nearest to (80, 100, 0)
+ font = bestMatchFromFamily(f->second, 80, 100, 0);
+ }
+
+ if (font != NULL)
+ break;
+ }
+
+ if (pass == 0) {
+ // didn't find it in our caches, so do a platform search (may be relatively expensive);
+ // this will update the caches with any fonts that seem to match the name given,
+ // so that the second pass might find it
+ searchForHostPlatformFonts(nameStr);
+ }
+ }
+
+ if (font == NULL)
+ return 0;
+
+ Family* parent = font->parent;
+
+ // if there are variant requests, try to apply them
+ // and delete B, I, and S=... codes from the string, just retain /engine option
+ sReqEngine = 0;
+ bool reqBold = false;
+ bool reqItal = false;
+ if (variant != NULL) {
+ std::string varString;
+ char* cp = variant;
+ while (*cp) {
+ if (strncmp(cp, "AAT", 3) == 0) {
+ sReqEngine = 'A';
+ cp += 3;
+ if (varString.length() > 0 && *(varString.end() - 1) != '/')
+ varString.append("/");
+ varString.append("AAT");
+ goto skip_to_slash;
+ }
+ if (strncmp(cp, "ICU", 3) == 0) { // for backword compatability
+ sReqEngine = 'O';
+ cp += 3;
+ if (varString.length() > 0 && *(varString.end() - 1) != '/')
+ varString.append("/");
+ varString.append("OT");
+ goto skip_to_slash;
+ }
+ if (strncmp(cp, "OT", 2) == 0) {
+ sReqEngine = 'O';
+ cp += 2;
+ if (varString.length() > 0 && *(varString.end() - 1) != '/')
+ varString.append("/");
+ varString.append("OT");
+ goto skip_to_slash;
+ }
+ if (strncmp(cp, "GR", 2) == 0) {
+ sReqEngine = 'G';
+ cp += 2;
+ if (varString.length() > 0 && *(varString.end() - 1) != '/')
+ varString.append("/");
+ varString.append("GR");
+ goto skip_to_slash;
+ }
+ if (*cp == 'S') {
+ ++cp;
+ if (*cp == '=')
+ ++cp;
+ ptSize = 0.0;
+ while (*cp >= '0' && *cp <= '9') {
+ ptSize = ptSize * 10 + *cp - '0';
+ ++cp;
+ }
+ if (*cp == '.') {
+ double dec = 1.0;
+ ++cp;
+ while (*cp >= '0' && *cp <= '9') {
+ dec = dec * 10.0;
+ ptSize = ptSize + (*cp - '0') / dec;
+ ++cp;
+ }
+ }
+ goto skip_to_slash;
+ }
+
+ /* if the code is "B" or "I", we skip putting it in varString */
+ while (1) {
+ if (*cp == 'B') {
+ reqBold = true;
+ ++cp;
+ continue;
+ }
+ if (*cp == 'I') {
+ reqItal = true;
+ ++cp;
+ continue;
+ }
+ break;
+ }
+
+ skip_to_slash:
+ while (*cp && *cp != '/')
+ ++cp;
+ if (*cp == '/')
+ ++cp;
+ }
+ strcpy(variant, varString.c_str());
+
+ std::map<std::string,Font*>::iterator i;
+ if (reqItal) {
+ Font* bestMatch = font;
+ if (font->slant < parent->maxSlant)
+ // try for a face with more slant
+ bestMatch = bestMatchFromFamily(parent, font->weight, font->width, parent->maxSlant);
+
+ if (bestMatch == font && font->slant > parent->minSlant)
+ // maybe the slant is negated, or maybe this was something like "Times-Italic/I"
+ bestMatch = bestMatchFromFamily(parent, font->weight, font->width, parent->minSlant);
+
+ if (parent->minWeight == parent->maxWeight && bestMatch->isBold != font->isBold) {
+ // try again using the bold flag, as we can't trust weight values
+ Font* newBest = NULL;
+ for (i = parent->styles->begin(); i != parent->styles->end(); ++i) {
+ if (i->second->isBold == font->isBold) {
+ if (newBest == NULL && i->second->isItalic != font->isItalic) {
+ newBest = i->second;
+ break;
+ }
+ }
+ }
+ if (newBest != NULL)
+ bestMatch = newBest;
+ }
+
+ if (bestMatch == font) {
+ // maybe slant values weren't present; try the style bits as a fallback
+ bestMatch = NULL;
+ for (i = parent->styles->begin(); i != parent->styles->end(); ++i) {
+ if (i->second->isItalic == !font->isItalic) {
+ if (parent->minWeight != parent->maxWeight) {
+ // weight info was available, so try to match that
+ if (bestMatch == NULL || weightAndWidthDiff(i->second, font) < weightAndWidthDiff(bestMatch, font))
+ bestMatch = i->second;
+ } else {
+ // no weight info, so try matching style bits
+ if (bestMatch == NULL && i->second->isBold == font->isBold) {
+ bestMatch = i->second;
+ break; // found a match, no need to look further as we can't distinguish!
+ }
+ }
+ }
+ }
+ }
+ if (bestMatch != NULL)
+ font = bestMatch;
+ }
+
+ if (reqBold) {
+ // try for more boldness, with the same width and slant
+ Font* bestMatch = font;
+ if (font->weight < parent->maxWeight) {
+ // 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;
+ for (i = parent->styles->begin(); i != parent->styles->end(); ++i) {
+ if (i->second->isItalic == font->isItalic) {
+ if (newBest == NULL || weightAndWidthDiff(i->second, bestMatch) < weightAndWidthDiff(newBest, bestMatch))
+ newBest = i->second;
+ }
+ }
+ if (newBest != NULL)
+ bestMatch = newBest;
+ }
+ }
+ if (bestMatch == font && !font->isBold) {
+ for (i = parent->styles->begin(); i != parent->styles->end(); ++i) {
+ if (i->second->isItalic == font->isItalic && i->second->isBold) {
+ bestMatch = i->second;
+ break;
+ }
+ }
+ }
+ font = bestMatch;
+ }
+ }
+
+ // if there's optical size info, try to apply it
+ if (ptSize < 0.0)
+ ptSize = dsize;
+ if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize > 0.0) {
+ double bestMismatch = my_fmax(font->opSizeInfo.minSize - ptSize, ptSize - font->opSizeInfo.maxSize);
+ if (bestMismatch > 0.0) {
+ Font* bestMatch = font;
+ for (std::map<std::string,Font*>::iterator i = parent->styles->begin(); i != parent->styles->end(); ++i) {
+ if (i->second->opSizeInfo.subFamilyID != font->opSizeInfo.subFamilyID)
+ continue;
+ double mismatch = my_fmax(i->second->opSizeInfo.minSize - ptSize, ptSize - i->second->opSizeInfo.maxSize);
+ if (mismatch < bestMismatch) {
+ bestMatch = i->second;
+ bestMismatch = mismatch;
+ }
+ if (bestMismatch <= 0.0)
+ break;
+ }
+ font = bestMatch;
+ }
+ }
+
+ if (font != NULL && font->opSizeInfo.designSize != 0.0)
+ loadedfontdesignsize = unsigned(font->opSizeInfo.designSize * 65536.0 + 0.5);
+
+ if (gettracingfontsstate() > 0) {
+ begindiagnostic();
+ zprintnl(' ');
+ printcstring("-> ");
+ printcstring(getPlatformFontDesc(font->fontRef).c_str());
+ zenddiagnostic(0);
+ }
+
+ return font->fontRef;
+}
+
+const char*
+XeTeXFontMgr::getFullName(PlatformFontRef font) const
+{
+ std::map<PlatformFontRef,Font*>::const_iterator i = m_platformRefToFont.find(font);
+ if (i == m_platformRefToFont.end())
+ die("internal error %d in XeTeXFontMgr", 2);
+ if (i->second->m_fullName != NULL)
+ return i->second->m_fullName->c_str();
+ else
+ return i->second->m_psName->c_str();
+}
+
+int
+XeTeXFontMgr::weightAndWidthDiff(const Font* a, const Font* b) const
+{
+ if (a->weight == 0 && a->width == 0) {
+ // assume there was no OS/2 info
+ if (a->isBold == b->isBold)
+ return 0;
+ else
+ return 10000;
+ }
+
+ int widDiff = labs(a->width - b->width);
+ if (widDiff < 10)
+ widDiff *= 50;
+
+ return labs(a->weight - b->weight) + widDiff;
+}
+
+int
+XeTeXFontMgr::styleDiff(const Font* a, int wt, int wd, int slant) const
+{
+ int widDiff = labs(a->width - wd);
+ if (widDiff < 10)
+ widDiff *= 200;
+
+ return labs(labs(a->slant) - labs(slant)) * 2 + labs(a->weight - wt) + widDiff;
+}
+
+XeTeXFontMgr::Font*
+XeTeXFontMgr::bestMatchFromFamily(const Family* fam, int wt, int wd, int slant) const
+{
+ Font* bestMatch = NULL;
+ for (std::map<std::string,Font*>::iterator s = fam->styles->begin(); s != fam->styles->end(); ++s)
+ if (bestMatch == NULL || styleDiff(s->second, wt, wd, slant) < styleDiff(bestMatch, wt, wd, slant))
+ bestMatch = s->second;
+ return bestMatch;
+}
+
+const XeTeXFontMgr::OpSizeRec*
+XeTeXFontMgr::getOpSize(XeTeXFont font)
+{
+ hb_font_t* hbFont = ((XeTeXFontInst*)font)->getHbFont();
+ if (hbFont != NULL) {
+ hb_face_t* face = hb_font_get_face(hbFont);
+ OpSizeRec* pSizeRec = (OpSizeRec*) xmalloc(sizeof(OpSizeRec));
+
+ unsigned int designSize, minSize, maxSize;
+ bool ok = hb_ot_layout_get_size_params(face,
+ &designSize,
+ &pSizeRec->subFamilyID,
+ &pSizeRec->nameCode,
+ &minSize,
+ &maxSize);
+
+ if (ok) {
+ // Convert sizes from PostScript deci-points to TeX points
+ pSizeRec->designSize = designSize * 72.27 / 72.0 / 10.0;
+ pSizeRec->minSize = minSize * 72.27 / 72.0 / 10.0;
+ pSizeRec->maxSize = maxSize * 72.27 / 72.0 / 10.0;
+ return pSizeRec;
+ }
+
+ free(pSizeRec);
+ return NULL;
+ }
+
+ return NULL;
+}
+
+double
+XeTeXFontMgr::getDesignSize(XeTeXFont font)
+{
+ const OpSizeRec* pSizeRec = getOpSize(font);
+ if (pSizeRec != NULL)
+ return pSizeRec->designSize;
+ else
+ return 10.0;
+}
+
+void
+XeTeXFontMgr::getOpSizeRecAndStyleFlags(Font* theFont)
+{
+ XeTeXFont font = createFont(theFont->fontRef, 655360);
+ XeTeXFontInst* fontInst = (XeTeXFontInst*) font;
+ if (font != 0) {
+ const OpSizeRec* pSizeRec = getOpSize(font);
+ if (pSizeRec != NULL) {
+ theFont->opSizeInfo.designSize = pSizeRec->designSize;
+ if (pSizeRec->subFamilyID == 0
+ && pSizeRec->nameCode == 0
+ && pSizeRec->minSize == 0.0
+ && pSizeRec->maxSize == 0.0)
+ goto done_size; // feature is valid, but no 'size' range
+ theFont->opSizeInfo.subFamilyID = pSizeRec->subFamilyID;
+ theFont->opSizeInfo.nameCode = pSizeRec->nameCode;
+ theFont->opSizeInfo.minSize = pSizeRec->minSize;
+ theFont->opSizeInfo.maxSize = pSizeRec->maxSize;
+ }
+ done_size:
+
+ const TT_OS2* os2Table = (TT_OS2*) fontInst->getFontTable(ft_sfnt_os2);
+ if (os2Table != NULL) {
+ theFont->weight = os2Table->usWeightClass;
+ theFont->width = os2Table->usWidthClass;
+ uint16_t sel = os2Table->fsSelection;
+ theFont->isReg = (sel & (1 << 6)) != 0;
+ theFont->isBold = (sel & (1 << 5)) != 0;
+ theFont->isItalic = (sel & (1 << 0)) != 0;
+ }
+
+ const TT_Header* headTable = (TT_Header*) fontInst->getFontTable(ft_sfnt_head);
+ if (headTable != NULL) {
+ uint16_t ms = headTable->Mac_Style;
+ if ((ms & (1 << 0)) != 0)
+ theFont->isBold = true;
+ if ((ms & (1 << 1)) != 0)
+ theFont->isItalic = true;
+ }
+
+ const TT_Postscript* postTable = (const TT_Postscript*) fontInst->getFontTable(ft_sfnt_post);
+ if (postTable != NULL) {
+ theFont->slant = (int)(1000 * (tan(Fix2D(-postTable->italicAngle) * M_PI / 180.0)));
+ }
+ deleteFont(font);
+ }
+}
+
+// append a name but only if it's not already in the list
+void
+XeTeXFontMgr::appendToList(std::list<std::string>* list, const char* str)
+{
+ for (std::list<std::string>::const_iterator i = list->begin(); i != list->end(); ++i)
+ if (*i == str)
+ return;
+ list->push_back(str);
+}
+
+// prepend a name, removing it from later in the list if present
+void
+XeTeXFontMgr::prependToList(std::list<std::string>* list, const char* str)
+{
+ for (std::list<std::string>::iterator i = list->begin(); i != list->end(); ++i)
+ if (*i == str) {
+ list->erase(i);
+ break;
+ }
+ list->push_front(str);
+}
+
+void
+XeTeXFontMgr::addToMaps(PlatformFontRef platformFont, const NameCollection* names)
+{
+ if (m_platformRefToFont.find(platformFont) != m_platformRefToFont.end())
+ return; // this font has already been cached
+
+ if (names->m_psName.length() == 0)
+ return; // can't use a font that lacks a PostScript name
+
+ if (m_psNameToFont.find(names->m_psName) != m_psNameToFont.end())
+ return; // duplicates an earlier PS name, so skip
+
+ Font* thisFont = new Font(platformFont);
+ thisFont->m_psName = new std::string(names->m_psName);
+ getOpSizeRecAndStyleFlags(thisFont);
+
+ m_psNameToFont[names->m_psName] = thisFont;
+ m_platformRefToFont[platformFont] = thisFont;
+
+ if (names->m_fullNames.size() > 0)
+ thisFont->m_fullName = new std::string(*(names->m_fullNames.begin()));
+
+ if (names->m_familyNames.size() > 0)
+ thisFont->m_familyName = new std::string(*(names->m_familyNames.begin()));
+ else
+ thisFont->m_familyName = new std::string(names->m_psName);
+
+ if (names->m_styleNames.size() > 0)
+ thisFont->m_styleName = new std::string(*(names->m_styleNames.begin()));
+ else
+ thisFont->m_styleName = new std::string;
+
+ std::list<std::string>::const_iterator i;
+ for (i = names->m_familyNames.begin(); i != names->m_familyNames.end(); ++i) {
+ std::map<std::string,Family*>::iterator iFam = m_nameToFamily.find(*i);
+ Family* family;
+ if (iFam == m_nameToFamily.end()) {
+ family = new Family;
+ m_nameToFamily[*i] = family;
+ family->minWeight = thisFont->weight;
+ family->maxWeight = thisFont->weight;
+ family->minWidth = thisFont->width;
+ family->maxWidth = thisFont->width;
+ family->minSlant = thisFont->slant;
+ family->maxSlant = thisFont->slant;
+ } else {
+ family = iFam->second;
+ if (thisFont->weight < family->minWeight)
+ family->minWeight = thisFont->weight;
+ if (thisFont->weight > family->maxWeight)
+ family->maxWeight = thisFont->weight;
+ if (thisFont->width < family->minWidth)
+ family->minWidth = thisFont->width;
+ if (thisFont->width > family->maxWidth)
+ family->maxWidth = thisFont->width;
+ if (thisFont->slant < family->minSlant)
+ family->minSlant = thisFont->slant;
+ if (thisFont->slant > family->maxSlant)
+ family->maxSlant = thisFont->slant;
+ }
+
+ if (thisFont->parent == NULL)
+ thisFont->parent = family;
+
+ // ensure all style names in the family point to thisFont
+ for (std::list<std::string>::const_iterator j = names->m_styleNames.begin(); j != names->m_styleNames.end(); ++j) {
+ std::map<std::string,Font*>::iterator iFont = family->styles->find(*j);
+ if (iFont == family->styles->end())
+ (*family->styles)[*j] = thisFont;
+/*
+ else if (iFont->second != thisFont)
+ fprintf(stderr, "# Font name warning: ambiguous Style \"%s\" in Family \"%s\" (PSNames \"%s\" and \"%s\")\n",
+ j->c_str(), i->c_str(), iFont->second->m_psName->c_str(), thisFont->m_psName->c_str());
+*/
+ }
+ }
+
+ for (i = names->m_fullNames.begin(); i != names->m_fullNames.end(); ++i) {
+ std::map<std::string,Font*>::iterator iFont = m_nameToFont.find(*i);
+ if (iFont == m_nameToFont.end())
+ m_nameToFont[*i] = thisFont;
+/*
+ else if (iFont->second != thisFont)
+ fprintf(stderr, "# Font name warning: ambiguous FullName \"%s\" (PSNames \"%s\" and \"%s\")\n",
+ i->c_str(), iFont->second->m_psName->c_str(), thisFont->m_psName->c_str());
+*/
+ }
+}
+
+void
+XeTeXFontMgr::die(const char*s, int i) const
+{
+ fprintf(stderr, s, i);
+ fprintf(stderr, " - exiting\n");
+ exit(3);
+}
+
+void
+XeTeXFontMgr::terminate()
+{
+}
+