File indexing completed on 2024-05-12 16:06:37
0001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*- 0002 // fontMap.cpp 0003 // 0004 // Part of KDVI - A DVI previewer for the KDE desktop environment 0005 // 0006 // SPDX-FileCopyrightText: 2003 Stefan Kebekus 0007 // SPDX-License-Identifier: GPL-2.0-or-later 0008 0009 #include <config.h> 0010 0011 #ifdef HAVE_FREETYPE 0012 0013 #include "debug_dvi.h" 0014 #include "fontMap.h" 0015 #include <QFile> 0016 #include <QLoggingCategory> 0017 #include <QProcess> 0018 #include <QStandardPaths> 0019 #include <QTextStream> 0020 0021 //#define DEBUG_FONTMAP 0022 0023 fontMap::fontMap() 0024 { 0025 // Make sure kpsewhich is in PATH and not just in the CWD 0026 static const QString kpsewhichFullPath = QStandardPaths::findExecutable(QStringLiteral("kpsewhich")); 0027 0028 // Read the map file of ps2pk which will provide us with a 0029 // dictionary "TeX Font names" <-> "Name of font files, Font Names 0030 // and Encodings" (example: the font "Times-Roman" is called 0031 // "ptmr8y" in the DVI file, but the Type1 font file name is 0032 // "utmr8a.pfb". We use the map file of "ps2pk" because that program 0033 // has, like kdvi (and unlike dvips), no built-in fonts. 0034 0035 // Finding ps2pk.map is not easy. In teTeX < 3.0, the kpsewhich 0036 // program REQUIRES the option "--format=dvips config". In teTeX = 0037 // 3.0, the option "--format=map" MUST be used. Since there is no 0038 // way to give both options at the same time, there is seemingly no 0039 // other way than to try both options one after another. We use the 0040 // teTeX 3.0 format first. 0041 QProcess kpsewhich; 0042 kpsewhich.start(kpsewhichFullPath, QStringList() << QStringLiteral("--format=map") << QStringLiteral("ps2pk.map"), QIODevice::ReadOnly | QIODevice::Text); 0043 0044 if (!kpsewhich.waitForStarted()) { 0045 qCCritical(OkularDviDebug) << "fontMap::fontMap(): kpsewhich could not be started."; 0046 return; 0047 } 0048 0049 // We wait here while the external program runs concurrently. 0050 kpsewhich.waitForFinished(-1); 0051 0052 QString map_fileName = QString::fromLocal8Bit(kpsewhich.readAll()).trimmed(); 0053 if (map_fileName.isEmpty()) { 0054 // Map file not found? Then we try the teTeX < 3.0 way of finding 0055 // the file. 0056 kpsewhich.start(kpsewhichFullPath, QStringList() << QStringLiteral("--format=dvips config") << QStringLiteral("ps2pk.map"), QIODevice::ReadOnly | QIODevice::Text); 0057 if (!kpsewhich.waitForStarted()) { 0058 qCCritical(OkularDviDebug) << "fontMap::fontMap(): kpsewhich could not be started."; 0059 return; 0060 } 0061 0062 kpsewhich.waitForFinished(-1); 0063 0064 map_fileName = QString::fromLocal8Bit(kpsewhich.readAll()).trimmed(); 0065 // If both versions fail, then there is nothing left to do. 0066 if (map_fileName.isEmpty()) { 0067 qCCritical(OkularDviDebug) << "fontMap::fontMap(): The file 'ps2pk.map' could not be found by kpsewhich."; 0068 return; 0069 } 0070 } 0071 0072 QFile file(map_fileName); 0073 if (file.open(QIODevice::ReadOnly)) { 0074 QTextStream stream(&file); 0075 QString line; 0076 while (!stream.atEnd()) { 0077 line = stream.readLine().simplified(); 0078 if (line.isEmpty() || (line.at(0) == QLatin1Char('%'))) { 0079 continue; 0080 } 0081 0082 QString TeXName = line.section(QLatin1Char(' '), 0, 0); 0083 QString FullName = line.section(QLatin1Char(' '), 1, 1); 0084 QString fontFileName = line.section(QLatin1Char('<'), -1).trimmed().section(QLatin1Char(' '), 0, 0); 0085 QString encodingName = line.section(QLatin1Char('<'), -2, -2).trimmed().section(QLatin1Char(' '), 0, 0); 0086 // It seems that sometimes the encoding is prepended by the 0087 // letter '[', which we ignore 0088 if ((!encodingName.isEmpty()) && (encodingName[0] == QLatin1Char('['))) { 0089 encodingName = encodingName.mid(1); 0090 } 0091 0092 double slant = 0.0; 0093 int i = line.indexOf(QStringLiteral("SlantFont")); 0094 if (i >= 0) { 0095 bool ok; 0096 slant = line.left(i).section(QLatin1Char(' '), -1, -1, QString::SectionSkipEmpty).toDouble(&ok); 0097 if (ok == false) { 0098 slant = 0.0; 0099 } 0100 } 0101 0102 fontMapEntry &entry = fontMapEntries[TeXName]; 0103 0104 entry.slant = slant; 0105 entry.fontFileName = fontFileName; 0106 entry.fullFontName = FullName; 0107 if (encodingName.endsWith(QLatin1String(".enc"))) { 0108 entry.fontEncoding = encodingName; 0109 } else { 0110 entry.fontEncoding.clear(); 0111 } 0112 } 0113 file.close(); 0114 } else { 0115 qCCritical(OkularDviDebug) << QStringLiteral("fontMap::fontMap(): The file '%1' could not be opened.").arg(map_fileName); 0116 } 0117 0118 #ifdef DEBUG_FONTMAP 0119 qCDebug(OkularDviDebug) << "FontMap file parsed. Results:"; 0120 QMap<QString, fontMapEntry>::Iterator it; 0121 for (it = fontMapEntries.begin(); it != fontMapEntries.end(); ++it) 0122 qCDebug(OkularDviDebug) << "TeXName: " << it.key() << ", FontFileName=" << it.data().fontFileName << ", FullName=" << it.data().fullFontName << ", Encoding=" << it.data().fontEncoding << "."; 0123 ; 0124 #endif 0125 } 0126 0127 const QString &fontMap::findFileName(const QString &TeXName) 0128 { 0129 QMap<QString, fontMapEntry>::Iterator it = fontMapEntries.find(TeXName); 0130 0131 if (it != fontMapEntries.end()) { 0132 return it.value().fontFileName; 0133 } 0134 0135 static const QString nullstring; 0136 return nullstring; 0137 } 0138 0139 const QString &fontMap::findFontName(const QString &TeXName) 0140 { 0141 QMap<QString, fontMapEntry>::Iterator it = fontMapEntries.find(TeXName); 0142 0143 if (it != fontMapEntries.end()) { 0144 return it.value().fullFontName; 0145 } 0146 0147 static const QString nullstring; 0148 return nullstring; 0149 } 0150 0151 const QString &fontMap::findEncoding(const QString &TeXName) 0152 { 0153 QMap<QString, fontMapEntry>::Iterator it = fontMapEntries.find(TeXName); 0154 0155 if (it != fontMapEntries.end()) { 0156 return it.value().fontEncoding; 0157 } 0158 0159 static const QString nullstring; 0160 return nullstring; 0161 } 0162 0163 double fontMap::findSlant(const QString &TeXName) 0164 { 0165 QMap<QString, fontMapEntry>::Iterator it = fontMapEntries.find(TeXName); 0166 0167 if (it != fontMapEntries.end()) { 0168 return it.value().slant; 0169 } else { 0170 return 0.0; 0171 } 0172 } 0173 0174 #endif // HAVE_FREETYPE