Subversion Repositories Scribus

Rev

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