/* * KFontInst - KDE Font Installer * * Copyright 2003-2009 Craig Drummond * * ---- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include "Utils.h" #include "FontInst.h" #include "Misc.h" #include "Fc.h" #include "WritingSystems.h" namespace KFI { namespace Utils { bool isAAfm(const QString &fname) { if(Misc::checkExt(QFile::encodeName(fname), "afm")) // CPD? Is this a necessary check? { QFile file(fname); if(file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); QString line; for(int lc=0; lc<30 && !stream.atEnd(); ++lc) { line=stream.readLine(); if(line.contains("StartFontMetrics")) { file.close(); return true; } } file.close(); } } return false; } bool isAPfm(const QString &fname) { bool ok=false; // I know extension checking is bad, but Ghostscript's pf2afm requires the pfm file to // have the .pfm extension... QByteArray name(QFile::encodeName(fname)); if(Misc::checkExt(name, "pfm")) { // // OK, the extension matches, so perform a little contents checking... FILE *f=fopen(name.constData(), "r"); if(f) { static const unsigned long constCopyrightLen = 60; static const unsigned long constTypeToExt = 49; static const unsigned long constExtToFname = 20; static const unsigned long constExtLen = 30; static const unsigned long constFontnameMin = 75; static const unsigned long constFontnameMax = 512; unsigned short version=0, type=0, extlen=0; unsigned long length=0, fontname=0, fLength=0; fseek(f, 0, SEEK_END); fLength=ftell(f); fseek(f, 0, SEEK_SET); if(2==fread(&version, 1, 2, f) && // Read version 4==fread(&length, 1, 4, f) && // length... length==fLength && 0==fseek(f, constCopyrightLen, SEEK_CUR) && // Skip copyright notice... 2==fread(&type, 1, 2, f) && 0==fseek(f, constTypeToExt, SEEK_CUR) && 2==fread(&extlen, 1, 2, f) && extlen==constExtLen && 0==fseek(f, constExtToFname, SEEK_CUR) && 4==fread(&fontname, 1, 4, f) && fontname>constFontnameMin && fontname(0x80); FILE *f=fopen(name.constData(), "r"); if(f) { if(constPfbLen==fread(buffer, 1, constPfbLen, f)) match=buffer[0]==constPfbMarker && 0==memcmp(&buffer[constPfbOffset], constStr, constStrLen); fclose(f); } } return match; } static QString getMatch(const QString &file, const char *extension) { QString f(Misc::changeExt(file, extension)); return Misc::fExists(f) ? f : QString(); } void createAfm(const QString &file, EFileType type) { bool pfm=FILE_PFM==type, type1=FILE_SCALABLE==type && isAType1(file); if(type1 || pfm) { // pf2afm wants files with lowercase extension, so just check for lowercase! // -- when a font is installed, the extension is converted to lowercase anyway... QString afm=getMatch(file, "afm"); if(afm.isEmpty()) // No point creating if AFM already exists! { QString pfm, t1; if(type1) // Its a Type1, so look for existing PFM { pfm=getMatch(file, "pfm"); t1=file; } else // Its a PFM, so look for existing Type1 { t1=getMatch(file, "pfa"); if(t1.isEmpty()) t1=getMatch(file, "pfb"); pfm=file; } if(!t1.isEmpty() && !pfm.isEmpty()) // Do we have both Type1 and PFM? { QString rootName(t1.left(t1.length()-4)); Misc::doCmd("pf2afm", KShell::quoteArg(rootName)); // pf2afm wants name without extension... Misc::setFilePerms(QFile::encodeName(rootName+".afm")); } } } } EFileType check(const QString &file, Family &fam) { if(isAAfm(file)) return FILE_AFM; else if(isAPfm(file)) return FILE_PFM; else { // Check that file is a font via FreeType... int count=0; FcPattern *pat=FcFreeTypeQuery((const FcChar8 *)(QFile::encodeName(file).constData()), 0, NULL, &count); if(pat) { FcBool scalable; QString family, foundry; quint32 style; int index; qulonglong ws; EFileType type=(FcResultMatch!=FcPatternGetBool(pat, FC_SCALABLE, 0, &scalable) || !scalable) ? FILE_BITMAP : FILE_SCALABLE; FC::getDetails(pat, family, style, index, foundry); ws=WritingSystems::instance()->get(pat); FcPatternDestroy(pat); Style st(style, scalable, ws); st.add(File(file, foundry, index)); fam=Family(family); fam.add(st); return type; } } return FILE_INVALID; } } }