00001
00002
00003 #include "scribusapi.h"
00004 #include "fonts/scface.h"
00005 #include "text/storytext.h"
00006
00007 ScFace::ScFaceData::ScFaceData() :
00008 refs(0),
00009 usage(0),
00010 scName(""),
00011 fontFile("(None)"),
00012 faceIndex(-1),
00013 psName(""),
00014 family(""),
00015 style(""),
00016 variant(""),
00017 forDocument(""),
00018 status(ScFace::NULLFACE),
00019 typeCode(ScFace::UNKNOWN_TYPE),
00020 formatCode(ScFace::UNKNOWN_FORMAT),
00021 usable(false),
00022 embedPs(false),
00023 subset(false),
00024 isStroked(false),
00025 isFixedPitch(false),
00026 hasNames(false),
00027 maxGlyph(0),
00028 cachedStatus(ScFace::UNKNOWN)
00029 {
00030 }
00031
00032 double ScFace::ScFaceData::glyphKerning(uint , uint , double ) const
00033 {
00034 return 0.0;
00035 }
00036
00037
00038 bool ScFace::ScFaceData::glyphNames(QMap<uint, std::pair<QChar, QString> >& ) const
00039 {
00040 return false;
00041 }
00042
00043
00044 QMap<QString,QString> ScFace::ScFaceData::fontDictionary(double ) const
00045 {
00046 return QMap<QString, QString>();
00047 }
00048
00049
00050 GlyphMetrics ScFace::ScFaceData::glyphBBox(uint gl, double sz) const
00051 {
00052 GlyphMetrics res;
00053 if (gl == 0 || gl >= CONTROL_GLYPHS)
00054 { res.width = glyphWidth(gl, sz);
00055 res.ascent = (gl == 0? sz : 0);
00056 res.descent = 0;
00057 return res;
00058 }
00059 else if (! m_glyphWidth.contains(gl)) {
00060 loadGlyph(gl);
00061 }
00062 const struct GlyphData & data(m_glyphOutline[gl]);
00063 res.width = data.bbox_width * sz;
00064 res.ascent = data.bbox_ascent * sz;
00065 res.descent = data.bbox_descent * sz;
00066 return res;
00067 }
00068
00069
00070 double ScFace::ScFaceData::glyphWidth(uint gl, double size) const
00071 {
00072 if (gl >= CONTROL_GLYPHS)
00073 return 0.0;
00074 else if (gl == 0)
00075 return size;
00076 else if (! m_glyphWidth.contains(gl)) {
00077 loadGlyph(gl);
00078 }
00079 return m_glyphWidth[gl] * size;
00080 }
00081
00082
00083 FPointArray ScFace::ScFaceData::glyphOutline(uint gl, double sz) const
00084 {
00085 if (gl >= CONTROL_GLYPHS)
00086 return FPointArray();
00087 else if (gl == 0) {
00088 sz *= 10;
00089 FPointArray sq;
00090 sq.addQuadPoint(0,0,0,0,sz,0,sz,0);
00091 sq.addQuadPoint(sz,0,sz,0,sz,sz,sz,sz);
00092 sq.addQuadPoint(sz,sz,sz,sz,0,sz,0,sz);
00093 sq.addQuadPoint(0,sz,0,sz,0,0,0,0);
00094 return sq;
00095 }
00096 else if (! m_glyphWidth.contains(gl)) {
00097 loadGlyph(gl);
00098 }
00099 FPointArray res = m_glyphOutline[gl].Outlines.copy();
00100 if (sz != 1.0)
00101 res.scale(sz, sz);
00102 return res;
00103 }
00104
00105
00106 FPoint ScFace::ScFaceData::glyphOrigin(uint gl, double sz) const
00107 {
00108 if (gl == 0 || gl >= CONTROL_GLYPHS)
00109 return FPoint(0,0);
00110 else if (! m_glyphWidth.contains(gl)) {
00111 loadGlyph(gl);
00112 }
00113 const struct GlyphData & res(m_glyphOutline[gl]);
00114 return FPoint(res.x, res.y) * sz;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 ScFace::ScFace() : replacedName(), replacedInDoc()
00137 {
00138 m = new ScFaceData();
00139 m->refs = 1;
00140 m->usage = 0;
00141 }
00142
00143
00144 ScFace::ScFace(ScFaceData* data) : replacedName(), replacedInDoc()
00145 {
00146 m = data;
00147 ++(m->refs);
00148 m->cachedStatus = ScFace::UNKNOWN;
00149 }
00150
00151 ScFace::ScFace(const ScFace& other) : replacedName(other.replacedName), replacedInDoc(other.replacedInDoc)
00152 {
00153 m = other.m;
00154 ++(m->refs);
00155 }
00156
00157 ScFace::~ScFace()
00158 {
00159 if ( m && --(m->refs) == 0 ) {
00160 m->unload();
00161 delete m;
00162 m = 0;
00163 }
00164 }
00165
00166
00167 ScFace& ScFace::operator=(const ScFace& other)
00168 {
00169 if (m != other.m)
00170 {
00171 if (other.m)
00172 ++(other.m->refs);
00173 if ( m && --(m->refs) == 0 ) {
00174 m->unload();
00175 delete m;
00176 }
00177 m = other.m;
00178 }
00179 replacedName = other.replacedName;
00180 return *this;
00181 }
00182
00183
00187 bool ScFace::operator==(const ScFace& other) const
00188 {
00189 return replacedName == other.replacedName &&
00190 ( (isNone() && other.isNone() )
00191 || (m == other.m)
00192 || (m->family == other.m->family
00193 && m->style == other.m->style
00194 && m->variant == other.m->variant
00195 && m->fontFile == other.m->fontFile
00196 && m-> faceIndex == other.m->faceIndex) );
00197 }
00198
00199
00200 const ScFace& ScFace::none()
00201 {
00202 static ScFace NONE;
00203 return NONE;
00204 }
00205
00206
00207 void ScFace::increaseUsage() const
00208 {
00209 m->usage++;
00210 }
00211
00212
00213 void ScFace::decreaseUsage() const
00214 {
00215 if (m->usage == 1)
00216 unload();
00217 m->usage--;
00218 }
00219
00220
00221 void ScFace::unload() const
00222 {
00223 if (m->status >= ScFace::LOADED && usable()) {
00224 m->unload();
00225 }
00226
00227 m->m_glyphWidth.clear();
00228 m->m_glyphOutline.clear();
00229 m->m_cMap.clear();
00230 m->status = ScFace::UNKNOWN;
00231 }
00232
00233
00234 uint ScFace::emulateGlyph(QChar ch) const
00235 {
00236 if (ch == SpecialChars::LINEBREAK || ch == SpecialChars::PARSEP
00237 || ch == SpecialChars::FRAMEBREAK || ch == SpecialChars::COLBREAK
00238 || ch == SpecialChars::TAB || ch == SpecialChars::SHYPHEN
00239 || ch == SpecialChars::ZWSPACE || ch == SpecialChars::ZWNBSPACE)
00240 return CONTROL_GLYPHS + ch.unicode();
00241 else if (ch == SpecialChars::NBSPACE)
00242 return m->char2CMap(QChar(' '));
00243 else if(ch == SpecialChars::NBHYPHEN)
00244 return m->char2CMap(QChar('-'));
00245 else
00246 return 0;
00247 }
00248
00249
00250 uint ScFace::char2CMap(QChar ch) const
00251 {
00252 if (m->status == ScFace::UNKNOWN) {
00253 m->load();
00254 }
00255
00256 if (ch == SpecialChars::SHYPHEN)
00257 return emulateGlyph(ch);
00258
00259 uint gl = m->char2CMap(ch);
00260
00261 if (gl == 0)
00262 return emulateGlyph(ch);
00263 else
00264 return gl;
00265 }
00266
00267
00268 bool ScFace::canRender(QChar ch) const
00269 {
00270 if (!usable())
00271 return false;
00272 else {
00273 uint gl = char2CMap(ch);
00274 if (gl >= CONTROL_GLYPHS)
00275 return true;
00276 else if (gl != 0) {
00277 m->loadGlyph(gl);
00278 return ! m->m_glyphOutline[gl].broken;
00279 }
00280 else {
00281 return false;
00282 }
00283 }
00284 }
00285
00286
00287 double ScFace::charWidth(QChar ch, double size, QChar ch2) const
00288 {
00289 if (!canRender(ch))
00290 return size;
00291 else if (ch.unicode() == 28 || ch.unicode() == 13 || ch.unicode() == 9)
00292 return ch.unicode() == 9 ? 1.0 : 0.0;
00293 else {
00294 uint gl1 = char2CMap(ch);
00295 uint gl2 = char2CMap(ch2);
00296 double width = glyphWidth(gl1, size);
00297 if (gl2 != 0)
00298 width += glyphKerning(gl1, gl2, size);
00299
00300 return width;
00301 }
00302 }
00303
00304
00305 bool ScFace::EmbedFont(QString &str)
00306 {
00307 if (m->status == ScFace::UNKNOWN) {
00308 m->load();
00309 }
00310 return m->EmbedFont(str);
00311 }
00312
00313
00314 bool ScFace::glyphNames(QMap<uint, std::pair<QChar, QString> >& gList)
00315 {
00316 if (m->status == ScFace::UNKNOWN) {
00317 m->load();
00318 }
00319 return m->glyphNames(gList);
00320 }
00321
00322
00323 void ScFace::RawData(QByteArray & bb)
00324 {
00325 if (m->status == ScFace::UNKNOWN) {
00326 m->load();
00327 }
00328 m->RawData(bb);
00329 }
00330
00331 void ScFace::checkAllGlyphs()
00332 {
00333 if (m->status == ScFace::UNKNOWN) {
00334 m->load();
00335 }
00336 if (m->status != ScFace::LOADED) {
00337 return;
00338 }
00339 for (uint gl=0; gl <= m->maxGlyph; ++gl) {
00340 if (! m->m_glyphWidth.contains(gl)) {
00341 m->loadGlyph(gl);
00342 m->m_glyphWidth.remove(gl);
00343 m->m_glyphOutline.remove(gl);
00344 }
00345 }
00346 }