Subversion Repositories Scribus

Rev

Rev 5979 | Rev 6125 | Go to most recent revision | 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
 
76
        struct GlyphData {
77
                FPointArray Outlines;
78
                double x;
79
                double y;
80
                bool broken;
81
                GlyphData() : Outlines(), x(0), y(0), broken(true) {}
82
        };
83
 
84
 
85
        /// see accessors for ScFace for docs
86
        struct ScFaceData {
87
                /// controls destruction
88
                mutable int refs;
89
                /// controls load()
90
                mutable int usage;
91
 
92
                QString scName;
93
                QString fontFile;
94
                int     faceIndex;
95
                QString psName;
96
                QString family;
97
                QString style;
98
                QString variant;
99
 
100
                QString forDocument;
101
 
102
                mutable ScFace::Status status;
103
                ScFace::FontType typeCode;
104
                ScFace::FontFormat formatCode;
105
 
106
                bool usable;
107
                bool embedPs;
108
                bool subset;
109
 
110
                bool isStroked;
111
                bool isFixedPitch;
112
                bool hasNames;
113
                uint maxGlyph;
114
 
115
                virtual ~ScFaceData() { };
116
protected:
117
 
118
                friend class ScFace;
119
                Status cachedStatus;
120
 
121
                // caches
122
                mutable QMap<uint,double>    m_glyphWidth;
123
                mutable QMap<uint,GlyphData> m_glyphOutline;
124
                mutable QMap<uint, uint>     m_cMap;
125
 
126
                // fill caches & members
127
 
128
                virtual void load()             const
129
                {
130
                        m_glyphWidth.clear();
131
                        m_glyphOutline.clear();
132
                        m_cMap.clear();
133
 
134
                        status = QMAX(cachedStatus, ScFace::LOADED);
135
                }
136
 
137
                virtual void unload()           const
138
                {
139
                        m_glyphWidth.clear();
140
                        m_glyphOutline.clear();
141
                        m_cMap.clear();
142
 
143
                        status = ScFace::UNKNOWN;
144
                }
145
 
146
                virtual void loadGlyph(uint gl) const {}
147
 
148
                // dummy implementations
149
                virtual double ascent(double sz)           const { return sz; }
150
                virtual double descent(double sz)          const { return 0.0; }
151
                virtual double xHeight(double sz)          const { return sz; }
152
                virtual double capHeight(double sz)        const { return sz; }
153
                virtual double height(double sz)           const { return sz; }
154
                virtual double strikeoutPos(double sz)     const { return sz / 2; }
155
                virtual double underlinePos(double sz)     const { return -1.0; }
156
                virtual double strokeWidth(double sz)      const { return 0.1; }
157
                virtual double maxAdvanceWidth(double sz)  const { return sz; }
158
                virtual uint   char2CMap(QChar ch)         const { return 0; }
159
                virtual double glyphKerning(uint gl1, uint gl2, double sz) const;
160
                virtual QMap<QString,QString> fontDictionary(double sz=1.0) const;
161
                virtual GlyphMetrics glyphBBox(uint gl, double sz) const;
162
                virtual bool EmbedFont(QString &str)       const { return false; }
163
                virtual void RawData(QByteArray & bb)      const {}
164
                virtual bool glyphNames(QMap<QChar, std::pair<uint, QString> >& gList) const;
165
 
166
                // these use the cache:
167
                virtual double      glyphWidth(uint gl, double sz)   const;
168
                virtual FPointArray glyphOutline(uint gl, double sz) const;
169
                virtual FPoint      glyphOrigin (uint gl, double sz) const;
170
 
171
        };
172
 
173
 
174
 
175
        ScFace();
176
        ScFace(const ScFace& other);
177
        ~ScFace();
178
 
179
        /// used as a null object
180
        static const ScFace& none();
181
 
182
        /// test for null object
183
        bool isNone() const   { return m->status == NULLFACE; }
184
 
185
        ScFace& operator=(const ScFace& other);
186
        /** two ScFaces are equal if they either are both NULLFACEs or they
187
                agree on family, style, variant and fontpath
188
                */
189
        bool operator==(const ScFace& other) const ;
190
        bool operator!=(const ScFace& other) const { return ! (*this == other); }
191
 
192
 
193
        bool EmbedFont(QString &str);
194
        void RawData(QByteArray & bb);
195
        bool glyphNames(QMap<QChar, std::pair<uint, QString> >& gList);
196
 
197
        /// prevent unloading of face data
198
        void increaseUsage() const;
199
 
200
        /// unload face data if not used any more
201
        void decreaseUsage() const;
202
 
203
        /// unload face data. It will be reloaded on need
204
        void unload()      const;
205
 
206
        /// the name Scribus uses for this font
207
        QString scName()   const { return m->scName; }
208
 
209
        /// the name PostScript uses for this font
210
        QString psName()   const { return m->psName; }
211
 
212
        /// the physical location of the fontfile
213
        QString fontPath() const { return m->faceIndex >= 0 ? QString("%1(%2)").arg(m->fontFile).arg(m->faceIndex+1) : m->fontFile; }
214
 
215
        /// the file path of the fontfile
216
        QString fontFilePath()      const { return m->fontFile; }
217
 
218
        /// if the fontfile contains more than one face, the index, else -1
219
        int faceIndex()    const { return m->faceIndex; }
220
 
221
        /// path name of the document this face is local to
222
        QString localForDocument()  const { return m->forDocument; }
223
 
224
        /// font type, eg. Type1 or TTF
225
        FontType type()    const { return m->typeCode; }
226
 
227
        /// font format, which might be a little more complicated
228
        FontFormat format()const { return m->formatCode; }
229
 
230
        /// test if this face can be used in documents
231
        bool usable()      const { return m->usable && !isNone(); }
232
 
233
        /// test if this face can be embedded in PS/PDF
234
        bool embedPs()     const { return m->embedPs && m->status < BROKENGLYPHS; }
235
 
236
        /// test if this face can be embedded as outlines in PS/PDF
237
        bool subset()      const { return m->subset && m->status < BROKEN; }
238
 
239
        void usable(bool flag)   { m->usable = flag; }
240
        void embedPs(bool flag)  { m->embedPs = flag; }
241
        void subset(bool flag)   { m->subset = flag; }
242
 
243
        /// deprecated? tells if the face has PS names
244
        bool hasNames()    const { return m->hasNames; }
245
 
246
        /// tells if this font is an outline font
247
        bool isStroked()   const { return m->isStroked; }
248
 
249
        /// tells if this font is a fixed pitch font
250
        bool isFixedPitch()const { return m->isFixedPitch; }
251
 
252
        /// tells if this is an OTF/CFF font
253
        bool isOTF()       const { return m->typeCode == OTF; }
254
 
255
        /// returns the highest glyph index in this face
256
        uint maxGlyph()    const { return m->maxGlyph; }
257
 
258
        /// returns the font family as seen by Scribus
259
        QString family()   const { return m->family; }
260
 
261
        /// returns the font style as seen by Scribus (eg. bold, Italic)
262
        QString style()    const { return m->style; }
263
 
264
        /// returns an additional discriminating String for this face
265
        QString variant()  const { return m->variant; }
266
 
267
        // font metrics
268
        double ascent(double sz=1.0)          const { return m->ascent(sz); }
269
        double descent(double sz=1.0)         const { return m->descent(sz); }
270
        double xHeight(double sz=1.0)         const { return m->xHeight(sz); }
271
        double capHeight(double sz=1.0)       const { return m->capHeight(sz); }
272
        double height(double sz=1.0)          const { return m->height(sz); }
273
        double strikeoutPos(double sz=1.0)    const { return m->strikeoutPos(sz); }
274
        double underlinePos(double sz=1.0)    const { return m->underlinePos(sz); }
275
        double strokeWidth(double sz=1.0)     const { return m->strokeWidth(sz); }
276
        double maxAdvanceWidth(double sz=1.0) const { return m->maxAdvanceWidth(sz); }
277
 
278
        /// deprecated
279
        QString stemV(double sz=1.0)    const { return fontDictionary(sz)["/StemV"]; }
280
 
281
        /// deprecated
282
        QString italicAngle(double sz=1.0)      const { return fontDictionary(sz)["/ItalicAngle"]; }
283
 
284
        /// deprecated
285
        QString fontBBox(double sz=1.0)         const { return fontDictionary(sz)["/FontBBox"]; }
286
 
287
        /// returns a map of values used for font dictionaries in PS/PDF
288
        QMap<QString,QString> fontDictionary(double sz=1.0) const { return m->fontDictionary(sz); }    
289
        // glyph interface
290
 
291
        /// returns the glyphs normal advance width at size 'sz'
292
        double glyphWidth(uint gl, double sz=1.0) const { return m->glyphWidth(gl, sz); }
293
 
294
        /// returns the glyph kerning between 'gl1' and 'gl2' at size 'sz'
295
        double glyphKerning(uint gl1, uint gl2, double sz=1.0) const { return m->glyphKerning(gl1, gl2, sz); }
296
 
297
        /// returns the glyphs bounding box at size 'sz', ie. the area where this glyph will produce marks
298
        GlyphMetrics glyphBBox(uint gl, double sz=1.0) const { return m->glyphBBox(gl, sz); }
299
 
300
        /// returns the glyph's outline as a cubic Bezier path
301
        FPointArray glyphOutline(uint gl, double sz=1.0) const { return m->glyphOutline(gl, sz); }
302
 
303
        /// returns the glyph's origin FIXME: what's that exactly?
304
        FPoint glyphOrigin(uint gl, double sz=1.0)    const { return m->glyphOrigin(gl, sz); }
305
 
306
        // char interface
307
 
308
        /// test if the face can render this char
309
        bool canRender(QChar ch)   const;
310
 
311
        /// translate unicode to glyph index
312
        uint char2CMap(QChar ch)   const;
313
 
314
        /// returns the combined glyph width and kerning for 'ch' if followed by 'ch2'
315
        double charWidth(QChar ch, double sz=1.0, QChar ch2 = QChar(32)) const;
316
 
317
        /// deprecated, see glyphBBox()
318
        double realCharWidth(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).width; }
319
 
320
        /// deprecated, see glyphBBox()
321
        double realCharHeight(QChar ch, double sz=1.0) const { GlyphMetrics gm=glyphBBox(char2CMap(ch),sz); return gm.ascent + gm.descent; }
322
 
323
        /// deprecated, see glyphBBox()
324
        double realCharAscent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).ascent; }
325
 
326
        /// deprecated, see glyphBBox()
327
        double realCharDescent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).descent; }
328
 
329
private:
330
 
331
        friend class SCFonts;
332
 
333
        ScFace(ScFaceData* md);
334
        ScFaceData* m;
335
 
336
        void initFaceData();
337
        void checkAllGlyphs();
338
};
339
 
340
#endif