Subversion Repositories Scribus

Rev

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