2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 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 "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>
32 #include "KfiConstants.h"
34 #include "FontEngine.h"
35 #include <QtCore/QByteArray>
36 #include <QtCore/QFile>
37 #include <KDE/KIO/NetAccess>
40 using namespace Strigi
;
44 class FontThroughAnalyzerFactory
: public StreamThroughAnalyzerFactory
46 friend class FontThroughAnalyzer
;
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
®
);
71 void FontThroughAnalyzerFactory::registerFields(FieldRegister
®
)
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
86 list
<StreamThroughAnalyzerFactory
*> streamThroughAnalyzerFactories() const
88 list
<StreamThroughAnalyzerFactory
*> af
;
90 af
.push_back(new FontThroughAnalyzerFactory());
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
)
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";
128 FontThroughAnalyzer::FontThroughAnalyzer(const FontThroughAnalyzerFactory
*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();
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);
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
);
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
,
192 FcFontSet
*set
= FcFontList(0, pat
, os
);
194 FcPatternDestroy(pat
);
195 FcObjectSetDestroy(os
);
197 if(set
&& set
->nfont
)
201 QString
foundry(FC::getFcString(set
->fonts
[0], FC_FOUNDRY
, 0)),
204 FcPatternGetInteger(set
->fonts
[0], FC_SPACING
, 0, &spacing
);
205 FcPatternGetInteger(set
->fonts
[0], FC_FONTVERSION
, 0, &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),
217 else // Its a disabled font, so read file...
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
;
245 int n
=in
->read(d
, size
, -1);
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
));
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());