Subversion Repositories Scribus

Rev

Rev 8973 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5979 avox 1
#ifndef SC_FACE_H
2
#define SC_FACE_H
3
 
4
/* ScFace responsibilities:
5
 
6
font storage: type, format, filepath, index, document-local, substitute, etc.
7
usage:        use, embed, subset, ...
8
face info:    family, effect, alternative, flags, charset
9
encoding:     CMap2String, glyphnames,
10
metrics:      cwidth, bearing, bbox, "real" widths, paths
11
opentype:     apply features, script support (-)
12
embedding:    fontdictionary, rawdata, embedPS, embedPDF, subsetPS, subsetPDF
13
virtual:      dispatch to constituents, handle embedding (-)
14
*/
15
 
16
#include <qstring.h>
6079 fschmid 17
//#include <qvector.h>
5979 avox 18
#include <qmap.h>
6079 fschmid 19
//#include <qarray.h>
5979 avox 20
#include <utility>
21
 
22
#include "fpointarray.h"
23
 
24
 
25
 
26
struct GlyphMetrics {
27
        double width;
28
        double ascent;
29
        double descent;
30
};
31
 
32
 
33
 
34
/*! \brief Base Class ScFace : This is a total rewrite of the old Foi class.
35
 
36
It uses a shared private implementation which must be a subclass of ScFontData.
37
ScFace objects are quite small and can be handled like value objects. Reference
38
counting ensures that the shared data is freed when the last ScFace object is
39
destructed.
40
 
41
ScFaceData has caches for face and glyph data. load() fills those caches for
42
face data, loadGlyph() fills the cache for glyphs. caches are always filled by
43
need, so you can call unload() any time (well, better not multithreaded...)
44
without producing errors. the increaseUsage() and decreaseUsage() keep track
45
of at how many places a face is used and automatically unload when the count
46
reaches zero.
47
Other data is recalculated on demand. The implementation can choose to do its
48
own caching for this data.
49
 
50
ScFace uses a sophisticated lifecycle which controls the state of initialisation
51
and the performed checks. the normal lilecycle goes:
52
 
53
UNKNOWN  --load()-->  LOADED  --checkAllGlyphs()--> CHECKED
54
 
55
If the face can not be loaded, the status changes to BROKEN.
56
If only some glyphs can not be loaded, the status changes to
57
BROKENGLYPHS. These fonts can still be used  and subsetted(outlined),
58
but not embedded.
59
 
60
ScFace constructors are only accessible to the ScFonts class which does
61
some checking before creating a new ScFace. These checks are recorded
62
in a cache and only reexecuted if the font file changes.
63
The field 'cachedStatus' allows load() to switch directly to one of the
64
states BROKEN, CHECKED or BROKENGLYPHS if this state was reached during a
65
previous run of Scribus.
66
*/
67
class SCRIBUS_API ScFace
68
{
69
public:
70
        enum Status  { UNKNOWN, LOADED, CHECKED, BROKENGLYPHS, BROKEN, NULLFACE };
71
        enum FontType { TYPE0, TYPE1, TYPE3, TTF, CFF, OTF, UNKNOWN_TYPE };
72
        enum FontFormat { PFA, PFB, TYPE2, TYPE42,
73
                // handled by freetype: PFB_MAC, DFONT, HQX, MACBIN,
74
                SFNT, TTCF, UNKNOWN_FORMAT };
75
 
6144 avox 76
        static const uint CONTROL_GLYPHS = 2000000000; // 2 billion
77
 
5979 avox 78
        struct GlyphData {
79
                FPointArray Outlines;
80
                double x;
81
                double y;
8972 avox 82
                double bbox_width;
83
                double bbox_ascent;
84
                double bbox_descent;
5979 avox 85
                bool broken;
8973 avox 86
                GlyphData() : Outlines(), x(0), y(0), bbox_width(1), bbox_ascent(1), bbox_descent(0), broken(true) {}
5979 avox 87
        };
88
 
89
 
90
        /// see accessors for ScFace for docs
7153 jghali 91
        class ScFaceData {
92
        public:
5979 avox 93
                /// controls destruction
94
                mutable int refs;
95
                /// controls load()
96
                mutable int usage;
97
 
98
                QString scName;
99
                QString fontFile;
100
                int     faceIndex;
101
                QString psName;
102
                QString family;
103
                QString style;
104
                QString variant;
105
 
106
                QString forDocument;
107
 
108
                mutable ScFace::Status status;
109
                ScFace::FontType typeCode;
110
                ScFace::FontFormat formatCode;
111
 
112
                bool usable;
113
                bool embedPs;
114
                bool subset;
115
 
116
                bool isStroked;
117
                bool isFixedPitch;
118
                bool hasNames;
119
                uint maxGlyph;
7153 jghali 120
 
121
                ScFaceData();
5979 avox 122
                virtual ~ScFaceData() { };
7153 jghali 123
        protected:
5979 avox 124
 
125
                friend class ScFace;
126
                Status cachedStatus;
127
 
128
                // caches
129
                mutable QMap<uint,double>    m_glyphWidth;
130
                mutable QMap<uint,GlyphData> m_glyphOutline;
131
                mutable QMap<uint, uint>     m_cMap;
132
 
133
                // fill caches & members
134
 
135
                virtual void load()             const
136
                {
137
                        m_glyphWidth.clear();
138
                        m_glyphOutline.clear();
139
                        m_cMap.clear();
140
 
141
                        status = QMAX(cachedStatus, ScFace::LOADED);
142
                }
143
 
144
                virtual void unload()           const
145
                {
146
                        m_glyphWidth.clear();
147
                        m_glyphOutline.clear();
148
                        m_cMap.clear();
149
 
150
                        status = ScFace::UNKNOWN;
151
                }
152
 
6125 cbradney 153
                virtual void loadGlyph(uint /*gl*/) const {}
5979 avox 154
 
155
                // dummy implementations
156
                virtual double ascent(double sz)           const { return sz; }
6213 fschmid 157
                virtual QString ascentAsString()    const { return "0" ; }
158
                virtual QString descentAsString()    const { return "0"; }
159
                virtual QString capHeightAsString()    const { return "0"; }
160
                virtual QString FontBBoxAsString()    const { return "0 0 0 0"; }
161
                virtual QString ItalicAngleAsString()    const { return "0"; }
6125 cbradney 162
                virtual double descent(double /*sz*/)          const { return 0.0; }
5979 avox 163
                virtual double xHeight(double sz)          const { return sz; }
164
                virtual double capHeight(double sz)        const { return sz; }
165
                virtual double height(double sz)           const { return sz; }
166
                virtual double strikeoutPos(double sz)     const { return sz / 2; }
6125 cbradney 167
                virtual double underlinePos(double /*sz*/)     const { return -1.0; }
168
                virtual double strokeWidth(double /*sz*/)      const { return 0.1; }
5979 avox 169
                virtual double maxAdvanceWidth(double sz)  const { return sz; }
6125 cbradney 170
                virtual uint   char2CMap(QChar /*ch*/)         const { return 0; }
5979 avox 171
                virtual double glyphKerning(uint gl1, uint gl2, double sz) const;
172
                virtual QMap<QString,QString> fontDictionary(double sz=1.0) const;
173
                virtual GlyphMetrics glyphBBox(uint gl, double sz) const;
6125 cbradney 174
                virtual bool EmbedFont(QString &/*str*/)       const { return false; }
175
                virtual void RawData(QByteArray & /*bb*/)      const {}
6163 avox 176
                virtual bool glyphNames(QMap<uint, std::pair<QChar, QString> >& gList) const;
5979 avox 177
 
178
                // these use the cache:
179
                virtual double      glyphWidth(uint gl, double sz)   const;
180
                virtual FPointArray glyphOutline(uint gl, double sz) const;
181
                virtual FPoint      glyphOrigin (uint gl, double sz) const;
182
 
183
        };
184
 
185
 
186
 
187
        ScFace();
188
        ScFace(const ScFace& other);
189
        ~ScFace();
190
 
191
        /// used as a null object
192
        static const ScFace& none();
193
 
194
        /// test for null object
195
        bool isNone() const   { return m->status == NULLFACE; }
196
 
197
        ScFace& operator=(const ScFace& other);
198
        /** two ScFaces are equal if they either are both NULLFACEs or they
199
                agree on family, style, variant and fontpath
200
                */
201
        bool operator==(const ScFace& other) const ;
202
        bool operator!=(const ScFace& other) const { return ! (*this == other); }
203
 
204
 
205
        bool EmbedFont(QString &str);
206
        void RawData(QByteArray & bb);
6163 avox 207
        bool glyphNames(QMap<uint, std::pair<QChar, QString> >& gList);
5979 avox 208
 
209
        /// prevent unloading of face data
210
        void increaseUsage() const;
211
 
212
        /// unload face data if not used any more
213
        void decreaseUsage() const;
214
 
215
        /// unload face data. It will be reloaded on need
216
        void unload()      const;
217
 
218
        /// the name Scribus uses for this font
6733 avox 219
        QString scName()   const { return replacedName.isEmpty() ? m->scName : replacedName; }
5979 avox 220
 
6733 avox 221
        /// the name of the font which was used for replacement
222
        QString replacementName()   const { return m->scName; }
223
 
224
        /// the name of the font which was used for replacement
225
        QString replacementForDoc()   const { return replacedInDoc; }
226
 
227
        /// check if this is a replacement font
228
        bool isReplacement()   const { return !replacedName.isEmpty(); }
229
 
230
        /// makes a repalcement font for font "name" using this fonts data
231
        ScFace mkReplacementFor(QString name, QString doc) {
232
                ScFace result(m);
233
                result.replacedName = name;
234
                result.replacedInDoc = doc;
8716 avox 235
                return result;
236
        }
6733 avox 237
 
8716 avox 238
        void chReplacementTo(ScFace& other, QString doc) {
239
                QString oldName = replacedName;
240
                (*this) = other;
241
                replacedName = oldName;
242
                replacedInDoc = doc;
243
        }
244
 
5979 avox 245
        /// the name PostScript uses for this font
246
        QString psName()   const { return m->psName; }
247
 
248
        /// the physical location of the fontfile
249
        QString fontPath() const { return m->faceIndex >= 0 ? QString("%1(%2)").arg(m->fontFile).arg(m->faceIndex+1) : m->fontFile; }
250
 
251
        /// the file path of the fontfile
252
        QString fontFilePath()      const { return m->fontFile; }
253
 
254
        /// if the fontfile contains more than one face, the index, else -1
255
        int faceIndex()    const { return m->faceIndex; }
256
 
257
        /// path name of the document this face is local to
258
        QString localForDocument()  const { return m->forDocument; }
259
 
260
        /// font type, eg. Type1 or TTF
261
        FontType type()    const { return m->typeCode; }
262
 
263
        /// font format, which might be a little more complicated
264
        FontFormat format()const { return m->formatCode; }
265
 
266
        /// test if this face can be used in documents
267
        bool usable()      const { return m->usable && !isNone(); }
268
 
269
        /// test if this face can be embedded in PS/PDF
270
        bool embedPs()     const { return m->embedPs && m->status < BROKENGLYPHS; }
271
 
272
        /// test if this face can be embedded as outlines in PS/PDF
273
        bool subset()      const { return m->subset && m->status < BROKEN; }
274
 
275
        void usable(bool flag)   { m->usable = flag; }
276
        void embedPs(bool flag)  { m->embedPs = flag; }
277
        void subset(bool flag)   { m->subset = flag; }
278
 
279
        /// deprecated? tells if the face has PS names
280
        bool hasNames()    const { return m->hasNames; }
281
 
282
        /// tells if this font is an outline font
283
        bool isStroked()   const { return m->isStroked; }
284
 
285
        /// tells if this font is a fixed pitch font
286
        bool isFixedPitch()const { return m->isFixedPitch; }
287
 
288
        /// tells if this is an OTF/CFF font
289
        bool isOTF()       const { return m->typeCode == OTF; }
290
 
291
        /// returns the highest glyph index in this face
292
        uint maxGlyph()    const { return m->maxGlyph; }
293
 
294
        /// returns the font family as seen by Scribus
295
        QString family()   const { return m->family; }
296
 
297
        /// returns the font style as seen by Scribus (eg. bold, Italic)
298
        QString style()    const { return m->style; }
299
 
300
        /// returns an additional discriminating String for this face
301
        QString variant()  const { return m->variant; }
302
 
303
        // font metrics
304
        double ascent(double sz=1.0)          const { return m->ascent(sz); }
6213 fschmid 305
        QString ascentAsString()    const { return m->ascentAsString() ; }
306
        QString descentAsString()    const { return m->descentAsString() ; }
307
        QString capHeightAsString()    const { return m->capHeightAsString() ; }
308
        QString FontBBoxAsString()    const { return m->FontBBoxAsString() ; }
309
        QString ItalicAngleAsString()    const { return m->ItalicAngleAsString() ; }
5979 avox 310
        double descent(double sz=1.0)         const { return m->descent(sz); }
311
        double xHeight(double sz=1.0)         const { return m->xHeight(sz); }
312
        double capHeight(double sz=1.0)       const { return m->capHeight(sz); }
313
        double height(double sz=1.0)          const { return m->height(sz); }
314
        double strikeoutPos(double sz=1.0)    const { return m->strikeoutPos(sz); }
315
        double underlinePos(double sz=1.0)    const { return m->underlinePos(sz); }
316
        double strokeWidth(double sz=1.0)     const { return m->strokeWidth(sz); }
317
        double maxAdvanceWidth(double sz=1.0) const { return m->maxAdvanceWidth(sz); }
318
 
319
        /// deprecated
320
        QString stemV(double sz=1.0)    const { return fontDictionary(sz)["/StemV"]; }
321
 
322
        /// deprecated
323
        QString italicAngle(double sz=1.0)      const { return fontDictionary(sz)["/ItalicAngle"]; }
324
 
325
        /// deprecated
326
        QString fontBBox(double sz=1.0)         const { return fontDictionary(sz)["/FontBBox"]; }
327
 
328
        /// returns a map of values used for font dictionaries in PS/PDF
329
        QMap<QString,QString> fontDictionary(double sz=1.0) const { return m->fontDictionary(sz); }    
330
        // glyph interface
331
 
332
        /// returns the glyphs normal advance width at size 'sz'
9007 avox 333
        double glyphWidth(uint gl, double sz=1.0) const { return m->glyphWidth(gl, sz); }
5979 avox 334
 
335
        /// returns the glyph kerning between 'gl1' and 'gl2' at size 'sz'
6144 avox 336
        double glyphKerning(uint gl1, uint gl2, double sz=1.0) const { return QMAX(gl1,gl2) < CONTROL_GLYPHS ? m->glyphKerning(gl1, gl2, sz) : 0; }
5979 avox 337
 
338
        /// returns the glyphs bounding box at size 'sz', ie. the area where this glyph will produce marks
9007 avox 339
        GlyphMetrics glyphBBox(uint gl, double sz=1.0) const { return m->glyphBBox(gl, sz); }
5979 avox 340
 
341
        /// returns the glyph's outline as a cubic Bezier path
9007 avox 342
        FPointArray glyphOutline(uint gl, double sz=1.0) const { return m->glyphOutline(gl, sz); }
5979 avox 343
 
344
        /// returns the glyph's origin FIXME: what's that exactly?
9007 avox 345
        FPoint glyphOrigin(uint gl, double sz=1.0)    const { return m->glyphOrigin(gl, sz); }
5979 avox 346
 
347
        // char interface
348
 
349
        /// test if the face can render this char
350
        bool canRender(QChar ch)   const;
351
 
352
        /// translate unicode to glyph index
353
        uint char2CMap(QChar ch)   const;
354
 
355
        /// returns the combined glyph width and kerning for 'ch' if followed by 'ch2'
6144 avox 356
        double charWidth(QChar ch, double sz=1.0, QChar ch2 = QChar(0)) const;
5979 avox 357
 
358
        /// deprecated, see glyphBBox()
359
        double realCharWidth(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).width; }
360
 
361
        /// deprecated, see glyphBBox()
362
        double realCharHeight(QChar ch, double sz=1.0) const { GlyphMetrics gm=glyphBBox(char2CMap(ch),sz); return gm.ascent + gm.descent; }
363
 
364
        /// deprecated, see glyphBBox()
365
        double realCharAscent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).ascent; }
366
 
367
        /// deprecated, see glyphBBox()
368
        double realCharDescent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).descent; }
369
 
370
private:
371
 
372
        friend class SCFonts;
373
 
374
        ScFace(ScFaceData* md);
375
        ScFaceData* m;
6733 avox 376
        QString replacedName;
377
        QString replacedInDoc;
5979 avox 378
 
379
        void initFaceData();
380
        void checkAllGlyphs();
6978 avox 381
        uint emulateGlyph(QChar c) const;
5979 avox 382
};
383
 
384
#endif