Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
5979 avox 1
 
2
 
3
#include "scribusapi.h"
4
#include "fonts/scface.h"
6144 avox 5
#include "text/storytext.h"
5979 avox 6
 
7153 jghali 7
ScFace::ScFaceData::ScFaceData() :
7650 jghali 8
        refs(0),
7153 jghali 9
        usage(0),
10
        scName(""),
11
        fontFile("(None)"),
12
        faceIndex(-1),
13
        psName(""),
14
        family(""),
15
        style(""),
16
        variant(""),
17
        forDocument(""),
18
        status(ScFace::NULLFACE),
19
        typeCode(ScFace::UNKNOWN_TYPE),
20
        formatCode(ScFace::UNKNOWN_FORMAT),
21
        usable(false),
22
        embedPs(false),
23
        subset(false),
24
        isStroked(false),
25
        isFixedPitch(false),
26
        hasNames(false),
27
        maxGlyph(0),
28
        cachedStatus(ScFace::UNKNOWN)
29
{
30
}
5979 avox 31
 
9007 avox 32
double ScFace::ScFaceData::glyphKerning(uint /*gl1*/, uint /*gl2*/, double /*sz*/) const
5979 avox 33
{
34
        return 0.0;
35
}
36
 
37
 
9007 avox 38
bool ScFace::ScFaceData::glyphNames(QMap<uint, std::pair<QChar, QString> >& /*gList*/) const
5979 avox 39
{
40
        return false;
41
}
42
 
43
 
9007 avox 44
QMap<QString,QString> ScFace::ScFaceData::fontDictionary(double /*sz*/) const
5979 avox 45
{
46
        return QMap<QString, QString>();
47
}
48
 
6302 avox 49
 
5979 avox 50
GlyphMetrics ScFace::ScFaceData::glyphBBox(uint gl, double sz) const
51
{
52
        GlyphMetrics res;
8972 avox 53
        if (gl == 0 || gl >= CONTROL_GLYPHS)
9007 avox 54
        {       res.width   = glyphWidth(gl, sz);
8972 avox 55
                res.ascent  = (gl == 0? sz : 0);
56
                res.descent = 0;
57
                return res;
58
        }
59
        else if (! m_glyphWidth.contains(gl)) {
60
                loadGlyph(gl);
61
        }                      
62
        const struct GlyphData & data(m_glyphOutline[gl]);
63
        res.width = data.bbox_width * sz;
64
        res.ascent = data.bbox_ascent * sz;
65
        res.descent = data.bbox_descent * sz;  
5979 avox 66
        return res;
67
}
68
 
69
 
70
double ScFace::ScFaceData::glyphWidth(uint gl, double size) const
71
{
6978 avox 72
        if (gl >= CONTROL_GLYPHS)
6935 avox 73
                return 0.0;
7503 avox 74
        else if (gl == 0)
75
                return size;
6935 avox 76
        else if (! m_glyphWidth.contains(gl)) {
5979 avox 77
                loadGlyph(gl);
78
        }              
79
        return m_glyphWidth[gl] * size;
80
}
81
 
82
 
83
FPointArray ScFace::ScFaceData::glyphOutline(uint gl, double sz) const
84
{
6978 avox 85
        if (gl >= CONTROL_GLYPHS)
6935 avox 86
                return FPointArray();
7503 avox 87
        else if (gl == 0) {
8074 avox 88
                sz *= 10;
7503 avox 89
                FPointArray sq;
90
                sq.addQuadPoint(0,0,0,0,sz,0,sz,0);
91
                sq.addQuadPoint(sz,0,sz,0,sz,sz,sz,sz);
92
                sq.addQuadPoint(sz,sz,sz,sz,0,sz,0,sz);
93
                sq.addQuadPoint(0,sz,0,sz,0,0,0,0);
94
                return sq;
95
        }
6935 avox 96
        else if (! m_glyphWidth.contains(gl)) {
5979 avox 97
                loadGlyph(gl);
98
        }                      
99
        FPointArray res = m_glyphOutline[gl].Outlines.copy();
100
        if (sz != 1.0)
101
                res.scale(sz, sz);
102
        return res;
103
}
104
 
105
 
106
FPoint ScFace::ScFaceData::glyphOrigin(uint gl, double sz) const
107
{
7503 avox 108
        if (gl == 0 || gl >= CONTROL_GLYPHS)
6935 avox 109
                return FPoint(0,0);
110
        else if (! m_glyphWidth.contains(gl)) {
5979 avox 111
                loadGlyph(gl);
112
        }                      
113
        const struct GlyphData & res(m_glyphOutline[gl]);
114
        return FPoint(res.x, res.y) * sz;
115
}
116
 
117
 
118
/*****
119
   ScFace lifecycle:  unchecked -> loaded -> glyphs checked
120
                               |         \-> broken glyphs
121
                                                           \-> broken
122
   usable() == ! broken
123
   embeddable() == glyphs_checked
124
 
125
   canRender(unicode) -> CharMap cache? -> loadChar/Glyph -> !broken
126
   Glyphs:  width    status
127
            -1000    unkown
128
            -2000    broken
129
            >= 0     ok, outline valid
130
   CharMap:  unicode -> glyph index
131
             uint[256][256]
132
   unicode ignores: < 32, ...
133
   unicode emulate: spaces, hyphen, ligatures?, diacritics?
134
 *****/
135
 
6733 avox 136
ScFace::ScFace() :  replacedName(), replacedInDoc()
5979 avox 137
{
138
        m = new ScFaceData();
139
        m->refs = 1;
140
        m->usage = 0;
141
}
142
 
143
 
6733 avox 144
ScFace::ScFace(ScFaceData* data) : replacedName(), replacedInDoc()
5979 avox 145
{
146
        m = data;
7650 jghali 147
        ++(m->refs);
5979 avox 148
        m->cachedStatus = ScFace::UNKNOWN;
149
}
150
 
6733 avox 151
ScFace::ScFace(const ScFace& other) : replacedName(other.replacedName), replacedInDoc(other.replacedInDoc)
5979 avox 152
{
153
        m = other.m;
154
        ++(m->refs);
155
}
156
 
157
ScFace::~ScFace()
158
{
159
        if ( m && --(m->refs) == 0 ) {
160
                m->unload();
161
                delete m;
162
                m = 0;
163
        }
164
}
165
 
166
 
167
ScFace& ScFace::operator=(const ScFace& other)
168
{
7147 jghali 169
        if (m != other.m)
170
        {
7602 avox 171
                if (other.m)
172
                        ++(other.m->refs);
7147 jghali 173
                if ( m && --(m->refs) == 0 ) {
174
                        m->unload();
175
                        delete m;
176
                }
7413 jghali 177
                m = other.m;
5979 avox 178
        }
6733 avox 179
        replacedName = other.replacedName;
5985 avox 180
        return *this;
5979 avox 181
}
182
 
183
 
184
/** two ScFaces are equal if they either are both NULLFACEs or they
185
agree on family, style, variant and fontpath
186
*/
187
bool ScFace::operator==(const ScFace& other) const
188
{
6733 avox 189
        return replacedName == other.replacedName &&
190
                ( (isNone() && other.isNone() )
5979 avox 191
                         || (m == other.m)
192
                         || (m->family == other.m->family
193
                                 && m->style == other.m->style
194
                                 && m->variant == other.m->variant
195
                                 && m->fontFile == other.m->fontFile
196
                                 && m-> faceIndex == other.m->faceIndex) );
197
}
198
 
199
 
200
const ScFace& ScFace::none()
201
{
202
        static ScFace NONE;
203
        return NONE;
204
}
205
 
206
 
207
void ScFace::increaseUsage() const
208
{
209
        m->usage++;
210
}
211
 
212
 
213
void ScFace::decreaseUsage() const
214
{
215
        if (m->usage == 1)
216
                unload();
217
        m->usage--;
218
}
219
 
220
 
221
void ScFace::unload() const
222
{
223
        if (m->status >= ScFace::LOADED && usable()) {
224
                m->unload();
225
        }
226
        // clear caches
227
        m->m_glyphWidth.clear();
228
        m->m_glyphOutline.clear();
229
        m->m_cMap.clear();
230
        m->status = ScFace::UNKNOWN;
231
}
232
 
233
 
6978 avox 234
uint ScFace::emulateGlyph(QChar ch) const
6144 avox 235
{
236
        if (ch == SpecialChars::LINEBREAK || ch == SpecialChars::PARSEP
237
                || ch == SpecialChars::FRAMEBREAK || ch == SpecialChars::COLBREAK
6935 avox 238
                || ch == SpecialChars::TAB || ch == SpecialChars::SHYPHEN
239
                 || ch == SpecialChars::ZWSPACE || ch == SpecialChars::ZWNBSPACE)
6978 avox 240
                return CONTROL_GLYPHS + ch.unicode();
6144 avox 241
        else if (ch == SpecialChars::NBSPACE)
6978 avox 242
                return  m->char2CMap(QChar(' '));
6144 avox 243
        else if(ch == SpecialChars::NBHYPHEN)
6978 avox 244
                return  m->char2CMap(QChar('-'));
6144 avox 245
        else
246
                return 0;
247
}
248
 
249
 
5979 avox 250
uint ScFace::char2CMap(QChar ch) const
251
{
252
        if (m->status == ScFace::UNKNOWN) {
253
                m->load();
254
        }
9007 avox 255
 
256
        if (ch == SpecialChars::SHYPHEN)
257
                return emulateGlyph(ch);
258
 
6144 avox 259
        uint gl = m->char2CMap(ch);
9007 avox 260
 
6144 avox 261
        if (gl == 0)
262
                return emulateGlyph(ch);
263
        else
264
                return gl;
5979 avox 265
}
266
 
267
 
268
bool ScFace::canRender(QChar ch) const
269
{
270
        if (!usable())
271
                return false;
272
        else {
6978 avox 273
                uint gl = char2CMap(ch);    //  calls load()
9007 avox 274
                if (gl >= CONTROL_GLYPHS)   //  those are always empty
6978 avox 275
                        return true;
276
                else if (gl != 0) {
5979 avox 277
                        m->loadGlyph(gl);
278
                        return ! m->m_glyphOutline[gl].broken;
279
                }
280
                else  {
281
                        return false;
282
                }
283
        }
284
}
285
 
286
 
287
double ScFace::charWidth(QChar ch, double size, QChar ch2) const
288
{
289
        if (!canRender(ch)) // calls loadGlyph()
290
                return size;
291
        else if (ch.unicode() == 28 || ch.unicode() == 13 || ch.unicode() == 9)
292
                return ch.unicode() == 9 ? 1.0 : 0.0;
293
        else {
294
                uint gl1 = char2CMap(ch);
6144 avox 295
                uint gl2 = char2CMap(ch2);
5979 avox 296
                double width = glyphWidth(gl1, size);
297
                if (gl2 != 0)
298
                        width += glyphKerning(gl1, gl2, size);
299
//              qDebug(QString("scface::glyphkerning: %1_%2 = %3 (%4, %5)").arg(ch).arg(ch2).arg(glyphKerning(gl1, gl2,size)).arg(gl1).arg(gl2));
300
                return width;
301
        }
302
}
303
 
304
 
305
bool ScFace::EmbedFont(QString &str)
306
{
307
        if (m->status == ScFace::UNKNOWN) {
308
                m->load();
309
        }
310
        return m->EmbedFont(str);
311
}
312
 
313
 
6163 avox 314
bool ScFace::glyphNames(QMap<uint, std::pair<QChar, QString> >& gList)
5979 avox 315
{
316
        if (m->status == ScFace::UNKNOWN) {
317
                m->load();
318
        }
319
        return m->glyphNames(gList);
320
}
321
 
322
 
323
void ScFace::RawData(QByteArray & bb)
324
{
325
        if (m->status == ScFace::UNKNOWN) {
326
                m->load();
327
        }
328
        m->RawData(bb);
329
}
330
 
331
void ScFace::checkAllGlyphs()
332
{
333
        if (m->status == ScFace::UNKNOWN) {
334
                m->load();
335
        }
336
        if (m->status != ScFace::LOADED) {
337
                return;
338
        }
339
        for (uint gl=0; gl <= m->maxGlyph; ++gl) {
340
                if (! m->m_glyphWidth.contains(gl)) {
341
                        m->loadGlyph(gl);
342
                        m->m_glyphWidth.remove(gl);
343
                        m->m_glyphOutline.remove(gl);
344
                }
345
        }
346
}