2
* KFontInst - KDE Font Installer
4
* Copyright 2003-2009 Craig Drummond <craig@kde.org>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; see the file COPYING. If not, write to
20
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
* Boston, MA 02110-1301, USA.
24
#include <QtCore/QFile>
25
#include <QtCore/QByteArray>
26
#include <QtCore/QTextStream>
28
#include <fontconfig/fontconfig.h>
33
#include "WritingSystems.h"
41
QString modifyName(const QString &fname)
43
static const char constSymbols[]={ '-', ' ', ':', ';', '/', '~', 0 };
47
for(int s=0; constSymbols[s]; ++s)
48
rv=rv.replace(constSymbols[s], '_');
50
int dotPos(rv.lastIndexOf('.'));
54
: rv.left(dotPos+1)+rv.mid(dotPos+1).toLower();
57
bool isAAfm(const QString &fname)
59
if(Misc::checkExt(QFile::encodeName(fname), "afm")) // CPD? Is this a necessary check?
63
if(file.open(QIODevice::ReadOnly))
65
QTextStream stream(&file);
68
for(int lc=0; lc<30 && !stream.atEnd(); ++lc)
70
line=stream.readLine();
72
if(line.contains("StartFontMetrics"))
86
bool isAPfm(const QString &fname)
90
// I know extension checking is bad, but Ghostscript's pf2afm requires the pfm file to
91
// have the .pfm extension...
92
QByteArray name(QFile::encodeName(fname));
94
if(Misc::checkExt(name, "pfm"))
97
// OK, the extension matches, so perform a little contents checking...
98
FILE *f=fopen(name.constData(), "r");
102
static const unsigned long constCopyrightLen = 60;
103
static const unsigned long constTypeToExt = 49;
104
static const unsigned long constExtToFname = 20;
105
static const unsigned long constExtLen = 30;
106
static const unsigned long constFontnameMin = 75;
107
static const unsigned long constFontnameMax = 512;
109
unsigned short version=0,
112
unsigned long length=0,
116
fseek(f, 0, SEEK_END);
118
fseek(f, 0, SEEK_SET);
120
if(2==fread(&version, 1, 2, f) && // Read version
121
4==fread(&length, 1, 4, f) && // length...
123
0==fseek(f, constCopyrightLen, SEEK_CUR) && // Skip copyright notice...
124
2==fread(&type, 1, 2, f) &&
125
0==fseek(f, constTypeToExt, SEEK_CUR) &&
126
2==fread(&extlen, 1, 2, f) &&
127
extlen==constExtLen &&
128
0==fseek(f, constExtToFname, SEEK_CUR) &&
129
4==fread(&fontname, 1, 4, f) &&
130
fontname>constFontnameMin && fontname<constFontnameMax)
139
// This function is *only* used for the generation of AFMs from PFMs.
140
bool isAType1(const QString &fname)
142
static const char constStr[]="%!PS-AdobeFont-";
143
static const unsigned int constStrLen=15;
144
static const unsigned int constPfbOffset=6;
145
static const unsigned int constPfbLen=constStrLen+constPfbOffset;
147
QByteArray name(QFile::encodeName(fname));
148
char buffer[constPfbLen];
151
if(Misc::checkExt(name, "pfa"))
153
FILE *f=fopen(name.constData(), "r");
157
if(constStrLen==fread(buffer, 1, constStrLen, f))
158
match=0==memcmp(buffer, constStr, constStrLen);
162
else if(Misc::checkExt(name, "pfb"))
164
static const char constPfbMarker = static_cast<char>(0x80);
166
FILE *f=fopen(name.constData(), "r");
170
if(constPfbLen==fread(buffer, 1, constPfbLen, f))
171
match=buffer[0]==constPfbMarker && 0==memcmp(&buffer[constPfbOffset], constStr,
180
static QString getMatch(const QString &file, const char *extension)
182
QString f(Misc::changeExt(file, extension));
184
return Misc::fExists(f) ? f : QString();
187
void createAfm(const QString &file, EFileType type)
189
bool pfm=FILE_PFM==type,
190
type1=FILE_SCALABLE==type && isAType1(file);
194
// pf2afm wants files with lowercase extension, so just check for lowercase!
195
// -- when a font is installed, the extension is converted to lowercase anyway...
196
QString afm=getMatch(file, "afm");
198
if(afm.isEmpty()) // No point creating if AFM already exists!
203
if(type1) // Its a Type1, so look for existing PFM
205
pfm=getMatch(file, "pfm");
208
else // Its a PFM, so look for existing Type1
210
t1=getMatch(file, "pfa");
212
t1=getMatch(file, "pfb");
216
if(!t1.isEmpty() && !pfm.isEmpty()) // Do we have both Type1 and PFM?
218
QString rootName(t1.left(t1.length()-4));
219
Misc::doCmd("pf2afm", KShell::quoteArg(rootName)); // pf2afm wants name without extension...
220
Misc::setFilePerms(QFile::encodeName(rootName+".afm"));
226
EFileType check(const QString &file, Family &fam)
230
else if(isAPfm(file))
234
// Check that file is a font via FreeType...
236
FcPattern *pat=FcFreeTypeQuery((const FcChar8 *)(QFile::encodeName(file).constData()), 0, NULL,
247
EFileType type=(FcResultMatch!=FcPatternGetBool(pat, FC_SCALABLE, 0, &scalable) || !scalable)
248
? FILE_BITMAP : FILE_SCALABLE;
250
FC::getDetails(pat, family, style, index, foundry);
251
ws=WritingSystems::instance()->get(pat);
252
FcPatternDestroy(pat);
253
Style st(style, scalable, ws);
254
st.add(File(file, foundry, index));