You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
423 lines
15 KiB
423 lines
15 KiB
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Class Name : KFI::KFileFont
|
|
// Author : Craig Drummond
|
|
// Project : K Font Installer
|
|
// Creation Date : 20/03/2003
|
|
// Version : $Revision$ $Date$
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// (C) Craig Drummond, 2003, 2004
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "KFileFont.h"
|
|
#include "KfiConstants.h"
|
|
#include <qfile.h>
|
|
#include <qtextstream.h>
|
|
#include <kgenericfactory.h>
|
|
#include <kio/netaccess.h>
|
|
|
|
static void addEntry(int face, QString &existing, const QString &add)
|
|
{
|
|
if(face>0)
|
|
existing.append(", ");
|
|
existing.append(add);
|
|
}
|
|
|
|
static int strToWeight(const QString &str)
|
|
{
|
|
if(NULL==str)
|
|
return FC_WEIGHT_MEDIUM;
|
|
else if(str.contains("Bold", false))
|
|
return FC_WEIGHT_BOLD;
|
|
else if(str.contains("Heavy", false))
|
|
return FC_WEIGHT_HEAVY;
|
|
else if(str.contains("Black", false))
|
|
return FC_WEIGHT_BLACK;
|
|
else if(str.contains("ExtraBold", false))
|
|
return FC_WEIGHT_EXTRABOLD;
|
|
else if(str.contains("UltraBold", false))
|
|
return FC_WEIGHT_ULTRABOLD;
|
|
else if(str.contains("ExtraLight", false))
|
|
return FC_WEIGHT_EXTRALIGHT;
|
|
else if(str.contains("UltraLight", false))
|
|
return FC_WEIGHT_ULTRALIGHT;
|
|
else if(str.contains("Light", false))
|
|
return FC_WEIGHT_LIGHT;
|
|
else if(str.contains("Medium", false) || str.contains("Normal", false) || str.contains("Roman", false))
|
|
return FC_WEIGHT_MEDIUM;
|
|
else if(str.contains("Regular", false))
|
|
return FC_WEIGHT_REGULAR;
|
|
else if(str.contains("SemiBold", false))
|
|
return FC_WEIGHT_SEMIBOLD;
|
|
else if(str.contains("DemiBold", false))
|
|
return FC_WEIGHT_DEMIBOLD;
|
|
else if(str.contains("Thin", false))
|
|
return FC_WEIGHT_THIN;
|
|
else if(str.contains("Book", false))
|
|
return FC_WEIGHT_NORMAL;
|
|
else if(str.contains("Demi", false))
|
|
return FC_WEIGHT_NORMAL;
|
|
else
|
|
return FC_WEIGHT_MEDIUM;
|
|
}
|
|
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
static int strToWidth(const QString &str)
|
|
{
|
|
if(str.isEmpty())
|
|
return FC_WIDTH_NORMAL;
|
|
else if(str.contains("UltraCondensed", false))
|
|
return FC_WIDTH_ULTRACONDENSED;
|
|
else if(str.contains("ExtraCondensed", false))
|
|
return FC_WIDTH_EXTRACONDENSED;
|
|
else if(str.contains("SemiCondensed", false))
|
|
return FC_WIDTH_SEMICONDENSED;
|
|
else if(str.contains("Condensed", false))
|
|
return FC_WIDTH_CONDENSED;
|
|
else if(str.contains("SemiExpanded", false))
|
|
return FC_WIDTH_SEMIEXPANDED;
|
|
else if(str.contains("UltraExpanded", false))
|
|
return FC_WIDTH_ULTRAEXPANDED;
|
|
else if(str.contains("ExtraExpanded", false))
|
|
return FC_WIDTH_EXTRAEXPANDED;
|
|
else if(str.contains("Expanded", false))
|
|
return FC_WIDTH_EXPANDED;
|
|
else
|
|
return FC_WIDTH_NORMAL;
|
|
}
|
|
#endif
|
|
|
|
struct FoundryMap
|
|
{
|
|
const char *noticeStr,
|
|
*foundry;
|
|
unsigned short len;
|
|
};
|
|
|
|
static const FoundryMap map[]= // These are (mainly) taken from type1inst
|
|
{
|
|
{ "Bigelow", "B&H", 3},
|
|
{ "Adobe", "Adobe", 5},
|
|
{ "Bitstream", "Bitstream", 9},
|
|
{ "Monotype", "Monotype", 8},
|
|
{ "Linotype", "Linotype", 8},
|
|
{ "LINOTYPE-HELL", "Linotype", 0},
|
|
{ "IBM", "IBM", 3},
|
|
{ "URW", "URW", 3},
|
|
{ "International Typeface Corporation", "ITC", 3},
|
|
{ "Tiro Typeworks", "Tiro", 4},
|
|
{ "XFree86", "XFree86", 7},
|
|
{ "Microsoft", "Microsoft", 9},
|
|
{ "Omega", "Omega", 5},
|
|
{ "Font21", "Hwan", 4},
|
|
{ "HanYang System", "Hanyang", 7},
|
|
{ "Richard Mitchell", "Mitchell", 8},
|
|
{ "Doug Miles", "Miles", 5},
|
|
{ "Hank Gillette", "Gillette", 8},
|
|
{ "Three Islands Press", "3ip", 3},
|
|
{ "MacroMind", "Macromind", 9},
|
|
{ "MWSoft", "MWSoft", 6},
|
|
{ "Digiteyes Multimedia", "DigitEyes", 9},
|
|
{ "ZSoft", "ZSoft", 5},
|
|
{ "Title Wave", "Titlewave", 9},
|
|
{ "Southern Software", "Southern", 8},
|
|
{ "Reasonable Solutions", "Reasonable", 10},
|
|
{ "David Rakowski", "Rakowski", 8},
|
|
{ "D. Rakowski", "Rakowski", 0},
|
|
{ "S. G. Moye", "Moye", 4},
|
|
{ "S.G. Moye", "Moye", 0},
|
|
{ "Andrew s. Meit", "Meit", 4},
|
|
{ "A.S.Meit", "Meit", 0},
|
|
{ "Hershey", "Hershey", 7},
|
|
{ "FontBank", "FontBank", 8},
|
|
{ "A. Carr", "Carr", 4},
|
|
{ "Brendel Informatik", "Brendel", 7},
|
|
{ "Jonathan Brecher", "Brecher", 7},
|
|
{ "SoftMaker", "Softmaker", 9},
|
|
{ "LETRASET", "Letraset", 8},
|
|
{ "Corel Corp", "Corel", 5},
|
|
{ "PUBLISHERS PARADISE", "Paradise", 8},
|
|
{ "Publishers Paradise", "Paradise", 0},
|
|
{ "Allied Corporation", "Allied", 6},
|
|
{ NULL, NULL, 0}
|
|
};
|
|
|
|
static const char * getFoundry(const char *notice)
|
|
{
|
|
const FoundryMap *entry;
|
|
|
|
if(notice)
|
|
for(entry=map; NULL!=entry->foundry; entry++)
|
|
if(NULL!=strstr(notice, entry->noticeStr))
|
|
return entry->foundry;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static bool readAfm(const QString &file, QString &full, QString &family, QString &foundry, QString &weight,
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
QString &width,
|
|
#endif
|
|
QString &spacing, QString &slant)
|
|
{
|
|
QFile f(file);
|
|
bool foundName=false,
|
|
foundFamily=false;
|
|
int intSpacing=FC_PROPORTIONAL,
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
intWidth=FC_WIDTH_NORMAL,
|
|
#endif
|
|
intWeight=FC_WEIGHT_NORMAL,
|
|
intSlant=FC_SLANT_ROMAN,
|
|
intItalic=FC_SLANT_ROMAN;
|
|
|
|
if(f.open(IO_ReadOnly))
|
|
{
|
|
QTextStream stream(&f);
|
|
QString line;
|
|
bool inMetrics=false;
|
|
|
|
while(!stream.atEnd())
|
|
{
|
|
line=stream.readLine();
|
|
line=line.simplifyWhiteSpace();
|
|
|
|
if(inMetrics)
|
|
{
|
|
if(0==line.find("FullName "))
|
|
{
|
|
full=line.mid(9);
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
intWidth=strToWidth(full);
|
|
#endif
|
|
foundName=true;
|
|
}
|
|
else if(0==line.find("FamilyName "))
|
|
{
|
|
family=line.mid(11);
|
|
foundFamily=true;
|
|
}
|
|
else if(0==line.find("Weight "))
|
|
intWeight=strToWeight(line.mid(7));
|
|
else if(0==line.find("ItalicAngle "))
|
|
intSlant=0.0f==line.mid(12).toFloat() ? FC_SLANT_ROMAN : FC_SLANT_ITALIC;
|
|
else if(0==line.find("IsFixedPitch "))
|
|
intSpacing=0==line.mid(13).find("false", 0, false) ? FC_PROPORTIONAL : FC_MONO;
|
|
else if(0==line.find("Notice "))
|
|
foundry=getFoundry(line.mid(7).latin1());
|
|
else if(0==line.find("StartCharMetrics"))
|
|
break;
|
|
}
|
|
else
|
|
if(0==line.find("StartFontMetrics"))
|
|
inMetrics=true;
|
|
};
|
|
f.close();
|
|
|
|
if(!foundFamily && foundName)
|
|
{
|
|
family=full;
|
|
foundFamily=true;
|
|
}
|
|
|
|
if(foundName && FC_SLANT_ITALIC==intItalic && (-1!=full.find("Oblique") || -1!=full.find("Slanted")))
|
|
intItalic=FC_SLANT_OBLIQUE;
|
|
}
|
|
|
|
if(foundName && foundFamily)
|
|
{
|
|
weight=KFI::CFcEngine::weightStr(intWeight, false);
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
width=KFI::CFcEngine::widthStr(intWidth, false);
|
|
#endif
|
|
slant=KFI::CFcEngine::slantStr(intSlant, false);
|
|
spacing=KFI::CFcEngine::spacingStr(intSpacing);
|
|
|
|
if(foundry.isEmpty())
|
|
foundry=i18n(KFI_UNKNOWN_FOUNDRY);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
typedef KGenericFactory<KFI::KFileFontPlugin> KFileFontPluginFactory;
|
|
K_EXPORT_COMPONENT_FACTORY(kfile_font, KFileFontPluginFactory("kfontinst"))
|
|
|
|
namespace KFI
|
|
{
|
|
|
|
KFileFontPlugin::KFileFontPlugin(QObject *parent, const char *name, const QStringList& args)
|
|
: KFilePlugin(parent, name, args)
|
|
{
|
|
KGlobal::locale()->insertCatalogue(KFI_CATALOGUE);
|
|
|
|
addMimeType("application/x-font-ttf"),
|
|
addMimeType("application/x-font-type1");
|
|
//addMimeType("application/x-font-speedo");
|
|
addMimeType("application/x-font-bdf");
|
|
addMimeType("application/x-font-pcf");
|
|
//addMimeType("application/x-font-snf");
|
|
addMimeType("application/x-font-otf");
|
|
addMimeType("application/x-font-ttc");
|
|
addMimeType("application/x-afm");
|
|
}
|
|
|
|
void KFileFontPlugin::addMimeType(const char *mime)
|
|
{
|
|
KFileMimeTypeInfo *info=addMimeTypeInfo(mime);
|
|
KFileMimeTypeInfo::GroupInfo *group=addGroupInfo(info, "General", i18n("General"));
|
|
|
|
addItemInfo(group, "Full", i18n("Full Name"), QVariant::String);
|
|
addItemInfo(group, "Family", i18n("Family"), QVariant::String);
|
|
addItemInfo(group, "Foundry", i18n("Foundry"), QVariant::String);
|
|
addItemInfo(group, "Weight", i18n("Weight"), QVariant::String);
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
addItemInfo(group, "Width", i18n("Width"), QVariant::String);
|
|
#endif
|
|
addItemInfo(group, "Spacing", i18n("Spacing"), QVariant::String);
|
|
addItemInfo(group, "Slant", i18n("Slant"), QVariant::String);
|
|
}
|
|
|
|
bool KFileFontPlugin::readInfo(KFileMetaInfo& info, uint what)
|
|
{
|
|
QString full,
|
|
lastFull,
|
|
family,
|
|
foundry,
|
|
weight,
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
width,
|
|
#endif
|
|
spacing,
|
|
slant,
|
|
fullAll,
|
|
familyAll,
|
|
foundryAll,
|
|
weightAll,
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
widthAll,
|
|
#endif
|
|
spacingAll,
|
|
slantAll;
|
|
KURL url(info.url());
|
|
QString fName;
|
|
bool fontsProt = KFI_KIO_FONTS_PROTOCOL == url.protocol(),
|
|
fileProt = "file" == url.protocol(),
|
|
downloaded = false,
|
|
status = false;
|
|
|
|
what=0;
|
|
|
|
if(!fontsProt && !fileProt && KIO::NetAccess::download(url, fName, NULL))
|
|
{
|
|
downloaded=true;
|
|
url=KURL(fName);
|
|
}
|
|
|
|
if(downloaded || fontsProt || fileProt)
|
|
{
|
|
if("application/x-afm"==info.mimeType()) // Then fontconfig can't give us the data :-(
|
|
status=readAfm(url.path(), fullAll, familyAll, foundryAll, weightAll,
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
widthAll,
|
|
#endif
|
|
spacingAll, slantAll);
|
|
else
|
|
for(int face=0; face<10; ++face) // How to get num faces from fontconfig? don't know - so just try 1st 10...
|
|
{
|
|
if(itsEngine.getInfo(url, face, full, family, foundry, weight,
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
width,
|
|
#endif
|
|
spacing, slant) &&
|
|
!full.isEmpty() && full!=lastFull)
|
|
{
|
|
addEntry(face, fullAll, full);
|
|
lastFull=full;
|
|
|
|
if(KFileMetaInfo::Fastest!=what)
|
|
{
|
|
addEntry(face, familyAll, family);
|
|
if(0==face)
|
|
{
|
|
foundryAll=foundry;
|
|
|
|
if(foundryAll.isEmpty())
|
|
foundryAll=i18n(KFI_UNKNOWN_FOUNDRY);
|
|
else
|
|
{
|
|
// Try to make sure foundry is capitalised, and looks the same as that of
|
|
// any AFM.
|
|
foundryAll[0]=foundryAll[0].upper();
|
|
|
|
const FoundryMap *entry;
|
|
|
|
for(entry=map; NULL!=entry->foundry; entry++)
|
|
if(foundryAll.length()==entry->len && foundryAll.contains(entry->foundry, false))
|
|
{
|
|
foundryAll=entry->foundry;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
addEntry(face, weightAll, weight);
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
addEntry(face, widthAll, width);
|
|
#endif
|
|
addEntry(face, spacingAll, spacing);
|
|
addEntry(face, slantAll, slant);
|
|
}
|
|
status=true;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if(status)
|
|
{
|
|
KFileMetaInfoGroup group;
|
|
|
|
group=appendGroup(info, "General");
|
|
appendItem(group, "Full", fullAll);
|
|
|
|
if(KFileMetaInfo::Fastest!=what)
|
|
{
|
|
appendItem(group, "Family", familyAll);
|
|
appendItem(group, "Foundry", foundryAll);
|
|
appendItem(group, "Weight", weightAll);
|
|
#ifndef KFI_FC_NO_WIDTHS
|
|
appendItem(group, "Width", widthAll);
|
|
#endif
|
|
appendItem(group, "Spacing", spacingAll);
|
|
appendItem(group, "Slant", slantAll);
|
|
}
|
|
}
|
|
|
|
if(downloaded)
|
|
KIO::NetAccess::removeTempFile(fName);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
}
|