//////////////////////////////////////////////////////////////////////////////// // // 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 <tqfile.h> #include <tqtextstream.h> #include <kgenericfactory.h> #include <tdeio/netaccess.h> static void addEntry(int face, TQString &existing, const TQString &add) { if(face>0) existing.append(", "); existing.append(add); } static int strToWeight(const TQString &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 TQString &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 TQString &file, TQString &full, TQString &family, TQString &foundry, TQString &weight, #ifndef KFI_FC_NO_WIDTHS TQString &width, #endif TQString &spacing, TQString &slant) { TQFile 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)) { TQTextStream stream(&f); TQString 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(tdefile_font, KFileFontPluginFactory("tdefontinst")) namespace KFI { KFileFontPlugin::KFileFontPlugin(TQObject *parent, const char *name, const TQStringList& args) : KFilePlugin(parent, name, args) { TDEGlobal::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"), TQVariant::String); addItemInfo(group, "Family", i18n("Family"), TQVariant::String); addItemInfo(group, "Foundry", i18n("Foundry"), TQVariant::String); addItemInfo(group, "Weight", i18n("Weight"), TQVariant::String); #ifndef KFI_FC_NO_WIDTHS addItemInfo(group, "Width", i18n("Width"), TQVariant::String); #endif addItemInfo(group, "Spacing", i18n("Spacing"), TQVariant::String); addItemInfo(group, "Slant", i18n("Slant"), TQVariant::String); } bool KFileFontPlugin::readInfo(KFileMetaInfo& info, uint what) { TQString 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()); TQString fName; bool fontsProt = KFI_TDEIO_FONTS_PROTOCOL == url.protocol(), fileProt = "file" == url.protocol(), downloaded = false, status = false; what=0; if(!fontsProt && !fileProt && TDEIO::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) TDEIO::NetAccess::removeTempFile(fName); } return status; } }