Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

scface.cpp

Go to the documentation of this file.
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 /*gl1*/, uint /*gl2*/, double /*sz*/) const 
00033 { 
00034     return 0.0; 
00035 }
00036 
00037 
00038 bool ScFace::ScFaceData::glyphNames(QMap<uint, std::pair<QChar, QString> >& /*gList*/) const 
00039 { 
00040     return false; 
00041 }
00042 
00043 
00044 QMap<QString,QString> ScFace::ScFaceData::fontDictionary(double /*sz*/) 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    ScFace lifecycle:  unchecked -> loaded -> glyphs checked
00120                                |         \-> broken glyphs
00121                                \-> broken
00122    usable() == ! broken
00123    embeddable() == glyphs_checked
00124    
00125    canRender(unicode) -> CharMap cache? -> loadChar/Glyph -> !broken
00126    Glyphs:  width    status
00127             -1000    unkown
00128             -2000    broken
00129             >= 0     ok, outline valid
00130    CharMap:  unicode -> glyph index
00131              uint[256][256]
00132    unicode ignores: < 32, ...
00133    unicode emulate: spaces, hyphen, ligatures?, diacritics?
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     // clear caches
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);    //  calls load()
00274         if (gl >= CONTROL_GLYPHS)   //  those are always empty
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)) // calls loadGlyph()
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 //      qDebug(QString("scface::glyphkerning: %1_%2 = %3 (%4, %5)").arg(ch).arg(ch2).arg(glyphKerning(gl1, gl2,size)).arg(gl1).arg(gl2));
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 }
Created with personalized Doxygen. This is documentation for GPL software Scribus - Open Source Desktop Publishing.