~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kcontrol/kfontinst/strigi-analyzer/FontThroughAnalyzer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * KFontInst - KDE Font Installer
 
3
 *
 
4
 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
 
5
 *
 
6
 * ----
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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.
 
22
 */
 
23
 
 
24
#include "FontThroughAnalyzer.h"
 
25
 
 
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>
 
39
 
 
40
using namespace Strigi;
 
41
using namespace std;
 
42
using namespace KFI;
 
43
 
 
44
class FontThroughAnalyzerFactory : public StreamThroughAnalyzerFactory
 
45
{
 
46
    friend class FontThroughAnalyzer;
 
47
 
 
48
    public:
 
49
 
 
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;
 
57
 
 
58
    const char * name() const
 
59
    {
 
60
        return "FontThroughAnalyzer";
 
61
    }
 
62
 
 
63
    StreamThroughAnalyzer * newInstance() const
 
64
    {
 
65
        return new FontThroughAnalyzer(this);
 
66
    }
 
67
 
 
68
    void registerFields(FieldRegister &reg);
 
69
};
 
70
 
 
71
void FontThroughAnalyzerFactory::registerFields(FieldRegister &reg)
 
72
{
 
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);
 
80
}
 
81
 
 
82
class Factory : public AnalyzerFactoryFactory
 
83
{
 
84
    public:
 
85
 
 
86
    list<StreamThroughAnalyzerFactory *> streamThroughAnalyzerFactories() const
 
87
    {
 
88
        list<StreamThroughAnalyzerFactory *> af;
 
89
 
 
90
        af.push_back(new FontThroughAnalyzerFactory());
 
91
        return af;
 
92
    }
 
93
};
 
94
 
 
95
// macro that initializes the Factory when the plugin is loaded
 
96
STRIGI_ANALYZER_FACTORY(Factory)
 
97
 
 
98
static QString getFamily(const QString &font)
 
99
{
 
100
    int     commaPos=font.lastIndexOf(',');
 
101
    return -1==commaPos ? font : font.left(commaPos);
 
102
}
 
103
 
 
104
static QString toMime(CFontEngine::EType type)
 
105
{
 
106
    switch(type)
 
107
    {
 
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;
 
123
    }
 
124
 
 
125
    return QString();
 
126
}
 
127
 
 
128
FontThroughAnalyzer::FontThroughAnalyzer(const FontThroughAnalyzerFactory *f)
 
129
                   : factory(f)
 
130
{
 
131
}
 
132
 
 
133
InputStream * FontThroughAnalyzer::connectInputStream(InputStream *in)
 
134
{
 
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);
 
139
 
 
140
    if(fontsProt)
 
141
    {
 
142
        // OK, it is a fonts:/ url - stat to get appropriate info
 
143
        QString       path,
 
144
                      name,
 
145
                      mime;
 
146
        quint32       styleInfo=KFI_NO_STYLE_INFO;
 
147
        KIO::UDSEntry udsEntry;
 
148
 
 
149
        if(KIO::NetAccess::stat(url, udsEntry, NULL))
 
150
        {
 
151
            if(udsEntry.numberValue(KIO::UDSEntry::UDS_HIDDEN, 0))
 
152
            {
 
153
                path=udsEntry.stringValue(UDS_EXTRA_FILE_NAME);
 
154
                face=udsEntry.numberValue(UDS_EXTRA_FILE_FACE, 0);
 
155
            }
 
156
            name=udsEntry.stringValue(KIO::UDSEntry::UDS_NAME);
 
157
            styleInfo=udsEntry.numberValue(UDS_EXTRA_FC_STYLE);
 
158
            mime=udsEntry.stringValue(KIO::UDSEntry::UDS_MIME_TYPE);
 
159
        }
 
160
 
 
161
        if(path.isEmpty())
 
162
        {
 
163
            // Enabled font...
 
164
            if(!name.isEmpty())
 
165
            {
 
166
                int weight, width, slant;
 
167
 
 
168
                FC::decomposeStyleVal(styleInfo, weight, width, slant);
 
169
                name=getFamily(name);
 
170
 
 
171
                FcObjectSet *os  = FcObjectSetBuild(FC_SPACING, FC_FOUNDRY, FC_FONTVERSION, (void *)0);
 
172
                FcPattern   *pat = FcPatternBuild(NULL,
 
173
                                                    FC_FAMILY, FcTypeString,
 
174
                                                    (const FcChar8 *)(name.toUtf8().data()),
 
175
                                                    FC_WEIGHT, FcTypeInteger, weight,
 
176
                                                    FC_SLANT, FcTypeInteger, slant,
 
177
#ifndef KFI_FC_NO_WIDTHS
 
178
                                                    FC_WIDTH, FcTypeInteger, width,
 
179
#endif
 
180
                                                    NULL);
 
181
 
 
182
                FcFontSet   *set = FcFontList(0, pat, os);
 
183
 
 
184
                FcPatternDestroy(pat);
 
185
                FcObjectSetDestroy(os);
 
186
 
 
187
                if(set && set->nfont)
 
188
                {
 
189
                    int     spacing,
 
190
                            version;
 
191
                    QString foundry(FC::getFcString(set->fonts[0], FC_FOUNDRY, 0)),
 
192
                            versionStr;
 
193
 
 
194
                    FcPatternGetInteger(set->fonts[0], FC_SPACING, 0, &spacing);
 
195
                    FcPatternGetInteger(set->fonts[0], FC_FONTVERSION, 0, &version);
 
196
 
 
197
                    if(version)
 
198
                        versionStr.setNum(CFontEngine::decodeFixed(version));
 
199
 
 
200
                    result(name, CFontEngine::fixFoundry(foundry),
 
201
                           KFI::FC::weightStr(weight, false), KFI::FC::widthStr(width, false),
 
202
                           KFI::FC::spacingStr(spacing), KFI::FC::slantStr(slant, false),
 
203
                           versionStr, mime);
 
204
                }
 
205
            }
 
206
        }
 
207
        else // It is a disabled font, so read file...
 
208
        {
 
209
            CFontEngine fe;
 
210
            QByteArray  data;
 
211
 
 
212
            if(fe.openFont(CFontEngine::TYPE_UNKNOWN, data,
 
213
                           QFile::encodeName(path).constData(), face) &&
 
214
               !fe.getFamilyName().isEmpty())
 
215
                result(fe.getFamilyName(), fe.getFoundry(),
 
216
                       KFI::FC::weightStr(fe.getWeight(), false),
 
217
                       KFI::FC::widthStr(fe.getWidth(), false),
 
218
                       KFI::FC::spacingStr(fe.getSpacing()),
 
219
                       KFI::FC::slantStr(fe.getItalic(), false), fe.getVersion(), mime);
 
220
        }
 
221
    }
 
222
 
 
223
    if( in != 0 && fileProt)
 
224
    {
 
225
        CFontEngine::EType type(CFontEngine::getType(analysisResult->path().c_str(), in));
 
226
 
 
227
        if(CFontEngine::TYPE_UNKNOWN!=type)
 
228
        {
 
229
            // For some reason, when called vie KFileMetaInfo in->size() is 0. So, set a maximum
 
230
            // size that we want to read in...
 
231
            static const int constMaxFileSize=30*1024*1024;
 
232
 
 
233
            int        size=in->size()>0 ? in->size() : constMaxFileSize;
 
234
            const char *d;
 
235
            int        n=in->read(d, size, -1);
 
236
 
 
237
            in->reset(0);
 
238
            if(n <= 0)
 
239
                return in;
 
240
 
 
241
            CFontEngine fe;
 
242
            QByteArray  data=QByteArray::fromRawData(d, n);
 
243
 
 
244
            face=Misc::getIntQueryVal(url, KFI_KIO_FACE, 0);
 
245
 
 
246
            if(fe.openFont(type, data, analysisResult->path().c_str(), face) &&
 
247
               !fe.getFamilyName().isEmpty())
 
248
                result(fe.getFamilyName(), fe.getFoundry(),
 
249
                       KFI::FC::weightStr(fe.getWeight(), false),
 
250
                       KFI::FC::widthStr(fe.getWidth(), false),
 
251
                       KFI::FC::spacingStr(fe.getSpacing()),
 
252
                       KFI::FC::slantStr(fe.getItalic(), false),
 
253
                       fe.getVersion(), toMime(type));
 
254
        }
 
255
    }
 
256
 
 
257
    return in;
 
258
}
 
259
 
 
260
void FontThroughAnalyzer::result(const QString &family, const QString &foundry, const QString &weight,
 
261
                                 const QString &width, const QString &spacing, const QString &slant,
 
262
                                 const QString &version, const QString &mime)
 
263
{
 
264
    analysisResult->addValue(factory->constFamilyNameField, (const char *)family.toUtf8());
 
265
    analysisResult->addValue(factory->constWeightField, (const char *)weight.toUtf8());
 
266
    analysisResult->addValue(factory->constSlantField, (const char *)slant.toUtf8());
 
267
    analysisResult->addValue(factory->constWidthField, (const char *)width.toUtf8());
 
268
    analysisResult->addValue(factory->constSpacingField, (const char *)spacing.toUtf8());
 
269
    analysisResult->addValue(factory->constFoundryField, foundry.isEmpty()
 
270
                                    ? (const char *)i18n(KFI_UNKNOWN_FOUNDRY).toUtf8()
 
271
                                    : (const char *)foundry.toUtf8());
 
272
    if(!version.isEmpty())
 
273
        analysisResult->addValue(factory->constVersionField, (const char *)version.toUtf8());
 
274
 
 
275
    analysisResult->setMimeType((const char *)mime.toUtf8());
 
276
}