Subversion Repositories Scribus

Rev

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