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