khtml Library API Documentation

font.cpp

00001 
00026 #include "font.h"
00027 #include "khtml_factory.h"
00028 #include "khtml_settings.h"
00029 
00030 #include <kdebug.h>
00031 #include <kglobal.h>
00032 
00033 #include <qpainter.h>
00034 #include <qfontdatabase.h>
00035 #include <qpaintdevicemetrics.h>
00036 
00037 using namespace khtml;
00038 
00039 void Font::drawText( QPainter *p, int x, int y, QChar *str, int slen, int pos, int len,
00040         int toAdd, QPainter::TextDirection d, int from, int to, QColor bg ) const
00041 {
00042     QString qstr = QConstString(str, slen).string();
00043     // hack for fonts that don't have a welldefined nbsp
00044     if ( !fontDef.hasNbsp ) {
00045         // str.setLength() always does a deep copy, so the replacement code below is safe.
00046         qstr.setLength( slen );
00047         QChar *uc = (QChar *)qstr.unicode();
00048         for( int i = 0; i < slen; i++ )
00049             if ( (uc+i)->unicode() == 0xa0 )
00050                 *(uc+i) = ' ';
00051     }
00052 
00053     // ### fixme for RTL
00054     if ( !letterSpacing && !wordSpacing && !toAdd && from==-1 ) {
00055         // simply draw it
00056         p->drawText( x, y, qstr, pos, len, d );
00057     } else {
00058         int numSpaces = 0;
00059         if ( toAdd ) {
00060             for( int i = 0; i < len; i++ )
00061                 if ( str[i+pos].direction() == QChar::DirWS )
00062                     numSpaces++;
00063         }
00064 
00065         if ( d == QPainter::RTL ) {
00066             x += width( str, slen, pos, len ) + toAdd;
00067         }
00068         for( int i = 0; i < len; i++ ) {
00069             int chw = fm.charWidth( qstr, pos+i );
00070             if ( letterSpacing )
00071                 chw += letterSpacing;
00072             if ( (wordSpacing || toAdd) && str[i+pos].isSpace() ) {
00073                 chw += wordSpacing;
00074                 if ( numSpaces ) {
00075                     int a = toAdd/numSpaces;
00076                     chw += a;
00077                     toAdd -= a;
00078                     numSpaces--;
00079                 }
00080             }
00081             if ( d == QPainter::RTL )
00082                 x -= chw;
00083             if ( to==-1 || (i>=from && i<to) )
00084             {
00085                 if ( bg.isValid() )
00086                     p->fillRect( x, y-fm.ascent(), chw, fm.height(), bg );
00087 
00088                 p->drawText( x, y, qstr, pos+i, 1, d );
00089             }
00090             if ( d != QPainter::RTL )
00091                 x += chw;
00092         }
00093     }
00094 }
00095 
00096 
00097 int Font::width( QChar *chs, int, int pos, int len ) const
00098 {
00099     QConstString cstr(chs+pos, len);
00100     int w;
00101 
00102     QString qstr = cstr.string();
00103     // hack for fonts that don't have a welldefined nbsp
00104     if ( !fontDef.hasNbsp ) {
00105         // str.setLength() always does a deep copy, so the replacement code below is safe.
00106         qstr.setLength( len );
00107         QChar *uc = (QChar *)qstr.unicode();
00108         for( int i = 0; i < len; i++ )
00109             if ( (uc+i)->unicode() == 0xa0 )
00110                 *(uc+i) = ' ';
00111     }
00112     // ### might be a little inaccurate
00113     w = fm.width( qstr );
00114 
00115     if ( letterSpacing )
00116         w += len*letterSpacing;
00117 
00118     if ( wordSpacing )
00119         // add amount
00120         for( int i = 0; i < len; i++ ) {
00121             if( chs[i+pos].isSpace() )
00122                 w += wordSpacing;
00123         }
00124 
00125     return w;
00126 }
00127 
00128 int Font::width( QChar *chs, int slen, int pos ) const
00129 {
00130     int w;
00131     if ( !fontDef.hasNbsp && (chs+pos)->unicode() == 0xa0 )
00132         w = fm.width( QChar( ' ' ) );
00133     else {
00134         QConstString cstr( chs, slen );
00135         w = fm.charWidth( cstr.string(), pos );
00136     }
00137     if ( letterSpacing )
00138         w += letterSpacing;
00139 
00140     if ( wordSpacing && (chs+pos)->isSpace() )
00141                 w += wordSpacing;
00142     return w;
00143 }
00144 
00145 
00146 void Font::update( QPaintDeviceMetrics* devMetrics ) const
00147 {
00148     f.setFamily( fontDef.family.isEmpty() ? KHTMLFactory::defaultHTMLSettings()->stdFontName() : fontDef.family );
00149     f.setItalic( fontDef.italic );
00150     f.setWeight( fontDef.weight );
00151 
00152     QFontDatabase db;
00153 
00154     int size = fontDef.size;
00155     int lDpiY = kMax(devMetrics->logicalDpiY(), 96);
00156 
00157     // ok, now some magic to get a nice unscaled font
00158     // all other font properties should be set before this one!!!!
00159     if( !db.isSmoothlyScalable(f.family(), db.styleString(f)) )
00160     {
00161         QValueList<int> pointSizes = db.smoothSizes(f.family(), db.styleString(f));
00162         // lets see if we find a nice looking font, which is not too far away
00163         // from the requested one.
00164         // kdDebug(6080) << "khtml::setFontSize family = " << f.family() << " size requested=" << size << endl;
00165 
00166         QValueList<int>::Iterator it;
00167         float diff = 1; // ### 100% deviation
00168         float bestSize = 0;
00169         for( it = pointSizes.begin(); it != pointSizes.end(); ++it )
00170         {
00171             float newDiff = ((*it)*(lDpiY/72.) - float(size))/float(size);
00172             //kdDebug( 6080 ) << "smooth font size: " << *it << " diff=" << newDiff << endl;
00173             if(newDiff < 0) newDiff = -newDiff;
00174             if(newDiff < diff)
00175             {
00176                 diff = newDiff;
00177                 bestSize = *it;
00178             }
00179         }
00180         //kdDebug( 6080 ) << "best smooth font size: " << bestSize << " diff=" << diff << endl;
00181         if ( bestSize != 0 && diff < 0.2 ) // 20% deviation, otherwise we use a scaled font...
00182             size = (int)((bestSize*lDpiY) / 72);
00183     }
00184 
00185     // make sure we don't bust up X11
00186     size = KMAX(0, KMIN(255, size));
00187 
00188 //       qDebug("setting font to %s, italic=%d, weight=%d, size=%d", fontDef.family.latin1(), fontDef.italic,
00189 //         fontDef.weight, size );
00190 
00191 
00192     f.setPixelSize( size );
00193 
00194     fm = QFontMetrics( f );
00195     fontDef.hasNbsp = fm.inFont( 0xa0 );
00196 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:33:49 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001