add more spacing
[personal-kdebase.git] / workspace / kcontrol / kfontinst / strigi-analyzer / FontThroughAnalyzer.cpp
blob0d983902f8b1cd8916d284d11716eabed7b5a3b4
1 /*
2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
6 * ----
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 "FontThroughAnalyzer.h"
26 #define STRIGI_IMPORT_API
27 #include <strigi/streamthroughanalyzer.h>
28 #include <strigi/analyzerplugin.h>
29 #include <strigi/fieldtypes.h>
30 #include <strigi/analysisresult.h>
31 #include "Fc.h"
32 #include "KfiConstants.h"
33 #include "Misc.h"
34 #include "FontEngine.h"
35 #include <QtCore/QByteArray>
36 #include <QtCore/QFile>
37 #include <KDE/KIO/NetAccess>
38 #include <list>
40 using namespace Strigi;
41 using namespace std;
42 using namespace KFI;
44 class FontThroughAnalyzerFactory : public StreamThroughAnalyzerFactory
46 friend class FontThroughAnalyzer;
48 public:
50 const RegisteredField * constFamilyNameField;
51 const RegisteredField * constFoundryField;
52 const RegisteredField * constWeightField;
53 const RegisteredField * constWidthField;
54 const RegisteredField * constSpacingField;
55 const RegisteredField * constSlantField;
56 const RegisteredField * constVersionField;
58 const char * name() const
60 return "FontThroughAnalyzer";
63 StreamThroughAnalyzer * newInstance() const
65 return new FontThroughAnalyzer(this);
68 void registerFields(FieldRegister &reg);
71 void FontThroughAnalyzerFactory::registerFields(FieldRegister &reg)
73 constFamilyNameField=reg.registerField("font.family", FieldRegister::stringType, 1, 0);
74 constWeightField=reg.registerField("font.weight", FieldRegister::stringType, 1, 0);
75 constSlantField=reg.registerField("font.slant", FieldRegister::stringType, 1, 0);
76 constWidthField=reg.registerField("font.width", FieldRegister::stringType, 1, 0);
77 constSpacingField=reg.registerField("font.spacing", FieldRegister::stringType, 1, 0);
78 constFoundryField=reg.registerField("font.foundry", FieldRegister::stringType, 1, 0);
79 constVersionField=reg.registerField("content.version", FieldRegister::stringType, 1, 0);
82 class Factory : public AnalyzerFactoryFactory
84 public:
86 list<StreamThroughAnalyzerFactory *> streamThroughAnalyzerFactories() const
88 list<StreamThroughAnalyzerFactory *> af;
90 af.push_back(new FontThroughAnalyzerFactory());
91 return af;
95 // macro that initializes the Factory when the plugin is loaded
96 STRIGI_ANALYZER_FACTORY(Factory)
98 static QString getFamily(const QString &font)
100 int commaPos=font.lastIndexOf(',');
101 return -1==commaPos ? font : font.left(commaPos);
104 static QString toMime(CFontEngine::EType type)
106 switch(type)
108 case CFontEngine::TYPE_OTF:
109 return "application/x-font-otf";
110 case CFontEngine::TYPE_TTF:
111 case CFontEngine::TYPE_TTC:
112 return "application/x-font-ttf";
113 case CFontEngine::TYPE_TYPE1:
114 return "application/x-font-type1";
115 case CFontEngine::TYPE_PCF:
116 return "application/x-font-pcf";
117 case CFontEngine::TYPE_BDF:
118 return "application/x-font-bdf";
119 case CFontEngine::TYPE_AFM:
120 return "application/x-font-afm";
121 default:
122 break;
125 return QString();
128 FontThroughAnalyzer::FontThroughAnalyzer(const FontThroughAnalyzerFactory *f)
129 : factory(f)
133 InputStream * FontThroughAnalyzer::connectInputStream(InputStream *in)
135 KUrl url(analysisResult->path().c_str());
136 bool fontsProt = KFI_KIO_FONTS_PROTOCOL == url.protocol(),
137 fileProt = "file" == url.protocol() || url.protocol().isEmpty();
138 int face(0);
140 if(fontsProt)
142 // OK, its a fonts:/ url - are we passed any data in the query?
143 QString path=url.queryItem(KFI_FILE_QUERY),
144 name=url.queryItem(KFI_NAME_QUERY),
145 mime=url.queryItem(KFI_MIME_QUERY);
146 quint32 styleInfo=Misc::getIntQueryVal(url, KFI_STYLE_QUERY, KFI_NO_STYLE_INFO);
148 face=Misc::getIntQueryVal(url, KFI_KIO_FACE, 0);
150 if(name.isEmpty() && path.isEmpty())
152 // OK, no useable info in the query - stat fonts:/ to get the required info...
153 KIO::UDSEntry udsEntry;
155 if(KIO::NetAccess::stat(url, udsEntry, NULL))
157 if(udsEntry.numberValue(KIO::UDSEntry::UDS_HIDDEN, 0))
159 path=udsEntry.stringValue(UDS_EXTRA_FILE_NAME);
160 face=Misc::getIntQueryVal(url, KFI_KIO_FACE, 0);
162 else
164 name=udsEntry.stringValue(KIO::UDSEntry::UDS_NAME);
165 styleInfo=udsEntry.numberValue(UDS_EXTRA_FC_STYLE);
167 mime=udsEntry.stringValue(KIO::UDSEntry::UDS_MIME_TYPE);
171 if(path.isNull())
173 // Enabled font...
174 if(!name.isNull())
176 int weight, width, slant;
178 FC::decomposeStyleVal(styleInfo, weight, width, slant);
179 name=getFamily(name);
181 FcObjectSet *os = FcObjectSetBuild(FC_SPACING, FC_FOUNDRY, FC_FONTVERSION, (void *)0);
182 FcPattern *pat = FcPatternBuild(NULL,
183 FC_FAMILY, FcTypeString,
184 (const FcChar8 *)(name.toUtf8().data()),
185 FC_WEIGHT, FcTypeInteger, weight,
186 FC_SLANT, FcTypeInteger, slant,
187 #ifndef KFI_FC_NO_WIDTHS
188 FC_WIDTH, FcTypeInteger, width,
189 #endif
190 NULL);
192 FcFontSet *set = FcFontList(0, pat, os);
194 FcPatternDestroy(pat);
195 FcObjectSetDestroy(os);
197 if(set && set->nfont)
199 int spacing,
200 version;
201 QString foundry(FC::getFcString(set->fonts[0], FC_FOUNDRY, 0)),
202 versionStr;
204 FcPatternGetInteger(set->fonts[0], FC_SPACING, 0, &spacing);
205 FcPatternGetInteger(set->fonts[0], FC_FONTVERSION, 0, &version);
207 if(version)
208 versionStr.setNum(CFontEngine::decodeFixed(version));
210 result(name, CFontEngine::fixFoundry(foundry),
211 KFI::FC::weightStr(weight, false), KFI::FC::widthStr(width, false),
212 KFI::FC::spacingStr(spacing), KFI::FC::slantStr(slant, false),
213 versionStr, mime);
217 else // Its a disabled font, so read file...
219 CFontEngine fe;
220 QByteArray data;
222 if(fe.openFont(CFontEngine::TYPE_UNKNOWN, data,
223 QFile::encodeName(path).constData(), face) &&
224 !fe.getFamilyName().isEmpty())
225 result(fe.getFamilyName(), fe.getFoundry(),
226 KFI::FC::weightStr(fe.getWeight(), false),
227 KFI::FC::widthStr(fe.getWidth(), false),
228 KFI::FC::spacingStr(fe.getSpacing()),
229 KFI::FC::slantStr(fe.getItalic(), false), fe.getVersion(), mime);
233 if( in != 0 && fileProt)
235 CFontEngine::EType type(CFontEngine::getType(analysisResult->path().c_str(), in));
237 if(CFontEngine::TYPE_UNKNOWN!=type)
239 // For some reason, when called vie KFileMetaInfo in->size() is 0. So, set a maximum
240 // size that we want to read in...
241 static const int constMaxFileSize=30*1024*1024;
243 int size=in->size()>0 ? in->size() : constMaxFileSize;
244 const char *d;
245 int n=in->read(d, size, -1);
247 in->reset(0);
248 if(-2==n)
249 return in;
251 CFontEngine fe;
252 QByteArray data=QByteArray::fromRawData(d, n);
254 face=Misc::getIntQueryVal(url, KFI_KIO_FACE, 0);
256 if(fe.openFont(type, data, analysisResult->path().c_str(), face) &&
257 !fe.getFamilyName().isEmpty())
258 result(fe.getFamilyName(), fe.getFoundry(),
259 KFI::FC::weightStr(fe.getWeight(), false),
260 KFI::FC::widthStr(fe.getWidth(), false),
261 KFI::FC::spacingStr(fe.getSpacing()),
262 KFI::FC::slantStr(fe.getItalic(), false),
263 fe.getVersion(), toMime(type));
267 return in;
270 void FontThroughAnalyzer::result(const QString &family, const QString &foundry, const QString &weight,
271 const QString &width, const QString &spacing, const QString &slant,
272 const QString &version, const QString &mime)
274 analysisResult->addValue(factory->constFamilyNameField, (const char *)family.toUtf8());
275 analysisResult->addValue(factory->constWeightField, (const char *)weight.toUtf8());
276 analysisResult->addValue(factory->constSlantField, (const char *)slant.toUtf8());
277 analysisResult->addValue(factory->constWidthField, (const char *)width.toUtf8());
278 analysisResult->addValue(factory->constSpacingField, (const char *)spacing.toUtf8());
279 analysisResult->addValue(factory->constFoundryField, foundry.isEmpty()
280 ? (const char *)i18n(KFI_UNKNOWN_FOUNDRY).toUtf8()
281 : (const char *)foundry.toUtf8());
282 if(!version.isEmpty())
283 analysisResult->addValue(factory->constVersionField, (const char *)version.toUtf8());
285 analysisResult->setMimeType((const char *)mime.toUtf8());