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, 0 insertions, 661 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
deleted file mode 100644
index 11094b10b47..00000000000
--- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
+++ /dev/null
@@ -1,661 +0,0 @@
-/****************************************************************************\
- 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()
-{
-}
-