summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Linux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Linux.cpp')
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Linux.cpp317
1 files changed, 317 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Linux.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Linux.cpp
new file mode 100644
index 00000000000..c10fc81f985
--- /dev/null
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Linux.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************\
+ Part of the XeTeX typesetting system
+ copyright (c) 1994-2006 by SIL International
+ written by Jonathan Kew
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL SIL INTERNATIONAL BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of SIL International
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written
+authorization from SIL International.
+\****************************************************************************/
+
+#include "XeTeXFontMgr_Linux.h"
+
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+
+#include "unicode/ucnv.h"
+
+#define kFontFamilyName 1
+#define kFontStyleName 2
+#define kFontFullName 4
+#define kPreferredFamilyName 16
+#define kPreferredSubfamilyName 17
+
+static UConverter* macRomanConv = NULL;
+static UConverter* utf16beConv = NULL;
+static UConverter* utf8Conv = NULL;
+
+static char*
+convertToUtf8(UConverter* conv, const unsigned char* name, int len)
+{
+static char* buffer1 = NULL;
+static char* buffer2 = NULL;
+static int bufSize = -1;
+
+ if (2 * (len + 1) > bufSize) {
+ if (buffer1 != NULL) {
+ delete[] buffer1;
+ delete[] buffer2;
+ }
+ bufSize = 2 * len + 100;
+ buffer1 = new char[bufSize];
+ buffer2 = new char[bufSize];
+ }
+
+ UErrorCode status = U_ZERO_ERROR;
+ len = ucnv_toUChars(conv, (UChar*)buffer1, bufSize, (const char*)name, len, &status);
+ len = ucnv_fromUChars(utf8Conv, buffer2, bufSize, (UChar*)buffer1, len, &status);
+ buffer2[len] = 0;
+
+ return buffer2;
+}
+
+XeTeXFontMgr::NameCollection*
+XeTeXFontMgr_Linux::readNames(FcPattern* pat)
+{
+ NameCollection* names = new NameCollection;
+
+ char* pathname;
+ if (FcPatternGetString(pat, FC_FILE, 0, (FcChar8**)&pathname) == FcTrue)
+ return names;
+ int index;
+ if (FcPatternGetInteger(pat, FC_INDEX, 0, &index) == FcTrue)
+ return names;
+
+ FT_Face face;
+ if (FT_New_Face(ftLib, pathname, index, &face) != 0)
+ return names;
+
+ const char* name = FT_Get_Postscript_Name(face);
+ if (name == NULL)
+ return names;
+ names->psName = name;
+
+ // for sfnt containers, we'll read the name table ourselves, not rely on Fontconfig
+ if (FT_IS_SFNT(face)) {
+ std::list<std::string> familyNames;
+ std::list<std::string> subFamilyNames;
+ FT_SfntName nameRec;
+ for (index = 0; index < FT_Get_Sfnt_Name_Count(face); ++index) {
+ char* utf8name = NULL;
+ if (FT_Get_Sfnt_Name(face, index, &nameRec) != 0)
+ continue;
+ switch (nameRec.name_id) {
+ case kFontFullName:
+ case kFontFamilyName:
+ case kFontStyleName:
+ case kPreferredFamilyName:
+ case kPreferredSubfamilyName:
+ {
+ bool preferredName = false;
+ if (nameRec.platform_id == TT_PLATFORM_MACINTOSH
+ && nameRec.encoding_id == TT_MAC_ID_ROMAN && nameRec.language_id == 0) {
+ utf8name = convertToUtf8(macRomanConv, nameRec.string, nameRec.string_len);
+ preferredName = true;
+ }
+ else if ((nameRec.platform_id == TT_PLATFORM_APPLE_UNICODE)
+ || (nameRec.platform_id == TT_PLATFORM_MICROSOFT))
+ utf8name = convertToUtf8(utf16beConv, nameRec.string, nameRec.string_len);
+
+ if (utf8name != NULL) {
+ std::list<std::string>* nameList = NULL;
+ switch (nameRec.name_id) {
+ case kFontFullName:
+ nameList = &names->fullNames;
+ break;
+ case kFontFamilyName:
+ nameList = &names->familyNames;
+ break;
+ case kFontStyleName:
+ nameList = &names->styleNames;
+ break;
+ case kPreferredFamilyName:
+ nameList = &familyNames;
+ break;
+ case kPreferredSubfamilyName:
+ nameList = &subFamilyNames;
+ break;
+ }
+ if (preferredName)
+ prependToList(nameList, utf8name);
+ else
+ appendToList(nameList, utf8name);
+ }
+ }
+ break;
+ }
+ }
+ if (familyNames.size() > 0)
+ names->familyNames = familyNames;
+ if (subFamilyNames.size() > 0)
+ names->styleNames = subFamilyNames;
+ }
+ else {
+ index = 0;
+ while (FcPatternGetString(pat, FC_FULLNAME, index++, (FcChar8**)&name) == FcFalse)
+ appendToList(&names->fullNames, name);
+ index = 0;
+ while (FcPatternGetString(pat, FC_FAMILY, index++, (FcChar8**)&name) == FcFalse)
+ appendToList(&names->familyNames, name);
+ index = 0;
+ while (FcPatternGetString(pat, FC_STYLE, index++, (FcChar8**)&name) == FcFalse)
+ appendToList(&names->styleNames, name);
+
+ if (names->fullNames.size() == 0) {
+ std::string fullName(names->familyNames.front());
+ if (names->styleNames.size() > 0) {
+ fullName += " ";
+ fullName += names->styleNames.front();
+ }
+ names->fullNames.push_back(fullName);
+ }
+ }
+
+ FT_Done_Face(face);
+
+ return names;
+}
+
+void
+XeTeXFontMgr_Linux::getOpSizeRecAndStyleFlags(Font* theFont)
+{
+ XeTeXFontMgr::getOpSizeRecAndStyleFlags(theFont);
+
+ if (theFont->weight == 0 && theFont->width == 0) {
+ // try to get values from FontConfig, as it apparently wasn't an sfnt
+ FcPattern* pat = theFont->fontRef;
+ int value;
+ if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &value) == FcFalse)
+ theFont->weight = value;
+ if (FcPatternGetInteger(pat, FC_WIDTH, 0, &value) == FcFalse)
+ theFont->width = value;
+ if (FcPatternGetInteger(pat, FC_SLANT, 0, &value) == FcFalse)
+ theFont->slant = value;
+ }
+}
+
+void
+XeTeXFontMgr_Linux::searchForHostPlatformFonts(const std::string& name)
+{
+ static bool cacheAll = false;
+ static FcFontSet* allFonts = NULL;
+
+ if (cacheAll) // we've already loaded everything on an earlier search
+ return;
+
+ if (allFonts == NULL) {
+ FcPattern* pat = FcNameParse((const FcChar8*)":outline=true");
+ FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FILE, FC_INDEX,
+ FC_FULLNAME, FC_WEIGHT, FC_WIDTH, FC_SLANT, NULL);
+
+ allFonts = FcFontList(FcConfigGetCurrent(), pat, os);
+
+ FcObjectSetDestroy(os);
+ FcPatternDestroy(pat);
+ }
+
+ std::string famName;
+ int hyph = name.find('-');
+ if (hyph > 0 && hyph < name.length() - 1)
+ famName.assign(name.begin(), name.begin() + hyph);
+ else
+ hyph = 0;
+
+ bool found = false;
+ while (1) {
+ for (int f = 0; f < allFonts->nfont; ++f) {
+ restart:
+ FcPattern* pat = allFonts->fonts[f];
+ if (platformRefToFont.find(pat) != platformRefToFont.end())
+ continue;
+
+ if (cacheAll) {
+ // failed to find it via FC; add everything to our maps (potentially slow) as a last resort
+ NameCollection* names = readNames(pat);
+ addToMaps(pat, names);
+ delete names;
+ continue;
+ }
+
+ char* s;
+ int i;
+ for (i = 0; FcPatternGetString(pat, FC_FULLNAME, i, (FcChar8**)&s) == FcFalse; ++i) {
+ if (name == s) {
+ NameCollection* names = readNames(pat);
+ addToMaps(pat, names);
+ delete names;
+ found = true;
+ goto next_font;
+ }
+ }
+
+ for (i = 0; FcPatternGetString(pat, FC_FAMILY, i, (FcChar8**)&s) == FcFalse; ++i) {
+ if (name == s || (hyph && famName == s)) {
+ NameCollection* names = readNames(pat);
+ addToMaps(pat, names);
+ delete names;
+ found = true;
+ goto next_font;
+ }
+ char* t;
+ for (int j = 0; FcPatternGetString(pat, FC_STYLE, j, (FcChar8**)&t) == FcFalse; ++j) {
+ std::string full(s);
+ full += " ";
+ full += t;
+ if (name == full) {
+ // need to ensure we'll pick up the whole family
+ famName = s;
+ hyph = 1;
+ f = 0;
+ goto restart;
+ }
+ }
+ }
+
+ next_font:
+ ;
+ }
+
+ if (found || cacheAll)
+ break;
+ cacheAll = true;
+ }
+}
+
+void
+XeTeXFontMgr_Linux::initialize()
+{
+ if (FcInit() == FcFalse) {
+ fprintf(stderr, "fontconfig initialization failed!\n");
+ exit(9);
+ }
+
+ if (FT_Init_FreeType(&ftLib) != 0) {
+ fprintf(stderr, "FreeType initialization failed!\n");
+ exit(9);
+ }
+
+ UErrorCode err = U_ZERO_ERROR;
+ macRomanConv = ucnv_open("macintosh", &err);
+ utf16beConv = ucnv_open("UTF16BE", &err);
+ utf8Conv = ucnv_open("UTF8", &err);
+ if (err != 0) {
+ fprintf(stderr, "internal error; cannot read font names\n");
+ exit(3);
+ }
+}
+
+void
+XeTeXFontMgr_Linux::terminate()
+{
+ if (macRomanConv != NULL)
+ ucnv_close(macRomanConv);
+ if (utf16beConv != NULL)
+ ucnv_close(utf16beConv);
+ if (utf8Conv != NULL)
+ ucnv_close(utf8Conv);
+}