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.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:33 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001