#include "font.h"
#include "khtml_factory.h"
#include "khtml_settings.h"
#include <kdebug.h>
#include <kglobal.h>
#include <qpainter.h>
#include <qfontdatabase.h>
#include <qpaintdevicemetrics.h>
#include <algorithm>
using namespace khtml;
#if APPLE_CHANGES
void Font::drawHighlightForText( QPainter *p, int x, int y, int h,
QChar *str, int slen, int pos, int len,
int toAdd, QPainter::TextDirection d, bool visuallyOrdered, int from, int to, QColor bg) const
{
p->drawHighlightForText(x, y, h, str + pos, std::min(slen - pos, len), from, to, toAdd, bg, d, visuallyOrdered,
letterSpacing, wordSpacing, fontDef.smallCaps);
}
#endif
void Font::drawText( QPainter *p, int x, int y, QChar *str, int slen, int pos, int len,
int toAdd, QPainter::TextDirection d, bool visuallyOrdered, int from, int to, QColor bg ) const
{
#if APPLE_CHANGES
p->drawText(x, y, str + pos, std::min(slen - pos, len), from, to, toAdd, bg, d, visuallyOrdered,
letterSpacing, wordSpacing, fontDef.smallCaps);
#else
QString qstr = QConstString(str, slen).string();
if ( !fontDef.hasNbsp ) {
qstr.setLength( slen );
QChar *uc = (QChar *)qstr.unicode();
for( int i = 0; i < slen; i++ )
if ( (uc+i)->unicode() == 0xa0 )
*(uc+i) = ' ';
}
if ( !letterSpacing && !wordSpacing && !toAdd && from==-1 ) {
p->drawText( x, y, qstr, pos, len, d );
} else {
int numSpaces = 0;
if ( toAdd ) {
for( int i = 0; i < len; i++ )
if ( str[i+pos].direction() == QChar::DirWS )
numSpaces++;
}
if ( d == QPainter::RTL ) {
x += width( str, slen, pos, len ) + toAdd;
}
for( int i = 0; i < len; i++ ) {
int chw = fm.charWidth( qstr, pos+i );
if ( letterSpacing )
chw += letterSpacing;
if ( (wordSpacing || toAdd) && str[i+pos].isSpace() ) {
chw += wordSpacing;
if ( numSpaces ) {
int a = toAdd/numSpaces;
chw += a;
toAdd -= a;
numSpaces--;
}
}
if ( d == QPainter::RTL )
x -= chw;
if ( to==-1 || (i>=from && i<to) )
{
if ( bg.isValid() )
p->fillRect( x, y-fm.ascent(), chw, fm.height(), bg );
p->drawText( x, y, qstr, pos+i, 1, d );
}
if ( d != QPainter::RTL )
x += chw;
}
}
#endif
}
#if APPLE_CHANGES
float Font::floatWidth( QChar *chs, int slen, int pos, int len ) const
{
return fm.floatWidth(chs, slen, pos, len, letterSpacing, wordSpacing, fontDef.smallCaps);
}
void Font::floatCharacterWidths( QChar *str, int slen, int pos, int len, int toAdd, float *buffer) const
{
fm.floatCharacterWidths(str, slen, pos, len, toAdd, buffer, letterSpacing, wordSpacing, fontDef.smallCaps);
}
int Font::checkSelectionPoint (QChar *s, int slen, int pos, int len, int toAdd, int x, bool reversed, bool includePartialGlyphs) const
{
return fm.checkSelectionPoint (s, slen, pos, len, toAdd, letterSpacing, wordSpacing, fontDef.smallCaps, x, reversed, includePartialGlyphs);
}
#endif
int Font::width( QChar *chs, int slen, int pos, int len ) const
{
#if APPLE_CHANGES
#ifndef ROUND_TO_INT
#define ROUND_TO_INT(x) (unsigned int)((x)+.5)
#endif
return ROUND_TO_INT(fm.floatWidth(chs+pos, slen-pos, 0, len, letterSpacing, wordSpacing, fontDef.smallCaps));
#else
QString qstr = QConstString(chs+pos, len).string();
if ( !fontDef.hasNbsp ) {
qstr.setLength( len );
QChar *uc = (QChar *)qstr.unicode();
for( int i = 0; i < len; i++ )
if ( (uc+i)->unicode() == 0xa0 )
*(uc+i) = ' ';
}
int w = fm.width( qstr );
if ( letterSpacing )
w += len*letterSpacing;
if ( wordSpacing )
for( int i = 0; i < len; i++ ) {
if( chs[i+pos].isSpace() )
w += wordSpacing;
}
return w;
#endif
}
int Font::width( QChar *chs, int slen, int pos ) const
{
#if APPLE_CHANGES
return width(chs, slen, pos, 1);
#else
int w;
if ( !fontDef.hasNbsp && (chs+pos)->unicode() == 0xa0 )
w = fm.width( QChar( ' ' ) );
else
w = fm.charWidth( QConstString( chs, slen).string(), pos );
if ( letterSpacing )
w += letterSpacing;
if ( wordSpacing && (chs+pos)->isSpace() )
w += wordSpacing;
return w;
#endif
}
void Font::update( QPaintDeviceMetrics* devMetrics ) const
{
#if APPLE_CHANGES
if (fontDef.family.familyIsEmpty())
f.setFamily(KHTMLFactory::defaultHTMLSettings()->stdFontName());
else
f.setFirstFamily(fontDef.family);
f.setItalic(fontDef.italic);
f.setWeight(fontDef.weight);
f.setPixelSize(fontDef.computedPixelSize());
f.setPrinterFont(fontDef.usePrinterFont);
fm.setFont(f);
#else
f.setFamily( fontDef.family.isEmpty() ? KHTMLFactory::defaultHTMLSettings()->stdFontName() : fontDef.family );
f.setItalic( fontDef.italic );
f.setWeight( fontDef.weight );
QFontDatabase db;
int size = fontDef.size;
int lDpiY = kMax(devMetrics->logicalDpiY(), 96);
if( !db.isSmoothlyScalable(f.family(), db.styleString(f)) )
{
QValueList<int> pointSizes = db.smoothSizes(f.family(), db.styleString(f));
QValueList<int>::Iterator it;
float diff = 1; float bestSize = 0;
for( it = pointSizes.begin(); it != pointSizes.end(); ++it )
{
float newDiff = ((*it)*(lDpiY/72.) - float(size))/float(size);
if(newDiff < 0) newDiff = -newDiff;
if(newDiff < diff)
{
diff = newDiff;
bestSize = *it;
}
}
if ( bestSize != 0 && diff < 0.2 ) size = (int)((bestSize*lDpiY) / 72);
}
size = KMAX(0, KMIN(255, size));
f.setPixelSize( size );
fm = QFontMetrics( f );
fontDef.hasNbsp = fm.inFont( 0xa0 );
#endif
}
#ifdef APPLE_CHANGES
bool Font::isFixedPitch() const
{
return f.isFixedPitch();
}
#endif