Back to index

scribus-ng  1.3.4.dfsg+svn20071115
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 }