00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "KoFontDiaPreview.h"
00021 #include "KoGlobal.h"
00022 #include "KoTextFormat.h"
00023
00024 #include <klocale.h>
00025
00026 #include <QFontMetrics>
00027 #include <QRect>
00028 #include <QPainter>
00029 #include <QFont>
00030 #include <QStringList>
00031 #include <QString>
00032 #include <QRegExp>
00033
00034 #include <Q3Frame>
00035
00036 #include <math.h>
00037
00038 #include "KoFontDiaPreview.moc"
00039
00040 KoFontDiaPreview::KoFontDiaPreview( QWidget* parent, const char* name , Qt::WFlags fl )
00041 : Q3Frame( parent, name, fl )
00042 ,m_text( i18n( "The quick brown fox jumps over the lazy dog." ) )
00043 ,displayText( i18n( "The quick brown fox jumps over the lazy dog." ) )
00044 ,m_font( KoGlobal::defaultFont() )
00045 ,m_textColor( Qt::black )
00046 ,m_backgroundColor( Qt::white )
00047 ,m_shadowDistanceX( 0 )
00048 ,m_shadowDistanceY( 0 )
00049 ,m_shadowColor( Qt::black )
00050 ,m_underlining( 0 )
00051 ,m_underliningStyle( 0 )
00052 ,m_underliningColor( Qt::black )
00053 ,m_wordByWord( false )
00054 ,m_strikethrough( 0 )
00055 ,m_strikethroughStyle( 0 )
00056 ,m_capitalisation( 0 )
00057 ,m_subSuper( 0 )
00058 ,m_offset( 0 )
00059 ,m_relativeSize( 1 )
00060
00061 {
00062 setFrameStyle( Q3Frame::WinPanel | Q3Frame::Plain );
00063 setBackgroundMode( Qt::PaletteBase );
00064 setBackgroundColor( Qt::white );
00065 setMinimumSize( 400, 100 );
00066 }
00067
00068 KoFontDiaPreview::~KoFontDiaPreview()
00069 {
00070 }
00071
00072 void KoFontDiaPreview::setText( const QString &text )
00073 {
00074 m_text = text;
00075 update();
00076 }
00077
00078 void KoFontDiaPreview::setFont( const QFont &font )
00079 {
00080 m_font = font;
00081 m_fontSize = m_font.pointSize();
00082 update();
00083 }
00084
00085 void KoFontDiaPreview::setFontColor( const QColor &textColor )
00086 {
00087 m_textColor = textColor;
00088 update();
00089 }
00090
00091 void KoFontDiaPreview::setBackgroundColor( const QColor &backgroundColor )
00092 {
00093 m_backgroundColor = backgroundColor;
00094 update();
00095 }
00096
00097 void KoFontDiaPreview::setShadow( double sdx, double sdy, QColor shadowColor )
00098 {
00099 m_shadowDistanceX = sdx;
00100 m_shadowDistanceY = sdy;
00101 m_shadowColor = shadowColor;
00102 update();
00103 }
00104
00105 void KoFontDiaPreview::setUnderlining( int underlining, int underliningStyle, const QColor underliningColor, bool wordByWord )
00106 {
00107 m_underlining = underlining;
00108 m_underliningStyle = underliningStyle;
00109 m_underliningColor = underliningColor;
00110 m_wordByWord = wordByWord;
00111 update();
00112 }
00113
00114 void KoFontDiaPreview::setWordByWord( bool wordByWord )
00115 {
00116 m_wordByWord = wordByWord;
00117 update();
00118 }
00119
00120 void KoFontDiaPreview::setStrikethrough( int strikethrough, int strikethroughStyle, bool wordByWord )
00121 {
00122 m_strikethrough = strikethrough;
00123 m_strikethroughStyle = strikethroughStyle;
00124 m_wordByWord = wordByWord;
00125 update();
00126 }
00127
00128 void KoFontDiaPreview::setCapitalisation( int capitalisation )
00129 {
00130 m_capitalisation = capitalisation;
00131 update();
00132 }
00133
00134 void KoFontDiaPreview::setSubSuperscript( int subSuper, int offset, double relativeSize )
00135 {
00136 m_subSuper = subSuper;
00137 m_offset = offset;
00138 m_relativeSize = relativeSize;
00139 update();
00140 }
00141
00142 QString KoFontDiaPreview::formatCapitalisation( const QString &string )
00143 {
00144 switch ( m_capitalisation )
00145 {
00146 case KoTextFormat::ATT_NONE :
00147 return string;
00148 case KoTextFormat::ATT_UPPER :
00149 return string.toUpper();
00150 case KoTextFormat::ATT_LOWER :
00151 return string.toLower();
00152 case KoTextFormat::ATT_SMALL_CAPS :
00153 return string.toUpper();
00154 default:
00155 return string;
00156 }
00157 }
00158
00159 void KoFontDiaPreview::drawContents( QPainter* p )
00160 {
00161 p->save();
00162
00163
00164
00165
00166 double capitalisationCoeff;
00167 QFontMetrics fmCapitalisation( m_font );
00168
00169 switch ( m_capitalisation )
00170 {
00171 case KoTextFormat::ATT_NONE :
00172 capitalisationCoeff = 1.0;
00173 break;
00174 case KoTextFormat::ATT_UPPER :
00175 capitalisationCoeff = 1.0;
00176 break;
00177 case KoTextFormat::ATT_LOWER :
00178 capitalisationCoeff = 1.0;
00179 break;
00180 case KoTextFormat::ATT_SMALL_CAPS :
00181 capitalisationCoeff = ((double)fmCapitalisation.boundingRect("x").height()/(double)fmCapitalisation.boundingRect("X").height());
00182 break;
00183 default:
00184 capitalisationCoeff = 1.0;
00185 break;
00186 }
00187
00188 displayFont = m_font;
00189 displayFont.setPointSizeF( m_font.pointSize() * capitalisationCoeff );
00190
00191
00192 displayText = formatCapitalisation( m_text );
00193
00194
00195 QFontMetrics fm( displayFont );
00196 QRect br = fm.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), Qt::AlignCenter | Qt::TextWordWrap, displayText );
00197
00198 if ( br.width() > contentsRect().width() || br.height() > contentsRect().height() ) {
00199 displayText = formatCapitalisation( i18n( "Font too large for the preview pane" ) );
00200 displayFont.setPointSizeF( 14 * capitalisationCoeff );
00201 }
00202
00203 QFontMetrics fm1( displayFont );
00204 br = fm1.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), Qt::AlignCenter | Qt::TextWordWrap, displayText );
00205
00206 int xorg = qRound( ( contentsRect().width() - br.width() ) / 2 ) + contentsRect().x() - fm1.leftBearing( displayText.at( 0 ) );
00207
00208
00209 int subSuperOffset = 0;
00210 switch ( m_subSuper ) {
00211 case 0:
00212 displayFont.setPointSizeF( displayFont.pointSize() * m_relativeSize );
00213 subSuperOffset = -( m_offset );
00214 break;
00215 case 1:
00216 displayFont.setPointSizeF( displayFont.pointSize() * m_relativeSize );
00217 subSuperOffset = fm1.height() / 6;
00218 break;
00219 case 2:
00220 displayFont.setPointSizeF( displayFont.pointSize() * m_relativeSize );
00221 subSuperOffset = 0 - ( fm1.height() / 2 );
00222 break;
00223 default:
00224 displayFont.setPointSizeF( displayFont.pointSize() * m_relativeSize );
00225 subSuperOffset = 0 - m_offset;
00226 break;
00227 }
00228
00229 QFontMetrics fm2( displayFont );
00230 br = fm2.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), Qt::AlignCenter | Qt::TextWordWrap, displayText );
00231 int yorg = qRound( ( contentsRect().height() - br.height() ) / 2 ) + fm1.ascent() + subSuperOffset;
00232 int sxorg = xorg + int( m_shadowDistanceX );
00233 int syorg = yorg + int( m_shadowDistanceY );
00234 QStringList textWords = QStringList::split( " ", displayText );
00235 int x = xorg;
00236 int y = yorg;
00237 int sx = sxorg;
00238 int sy = syorg;
00239 int bx= qMin( x, sx );
00240 int xend = bx;
00241 int yUnderline;
00242 int widthUnderline;
00243 int thicknessUnderline;
00244 int yStrikethrough;
00245 int widthStrikethrough;
00246 int thicknessStrikethrough;
00247
00248 p->setFont(displayFont );
00249 p->setPen( m_textColor );
00250 int count = 1;
00251
00252 for ( QStringList::iterator it = textWords.begin(); it != textWords.end(); ++it ) {
00253 int boffset = 0;
00254 if ( x + fm2.width( (*it) ) > contentsRect().width() ) {
00255 y += fm1.lineSpacing();
00256 sy += fm1.lineSpacing();
00257 xend = x;
00258 x = xorg;
00259 sx = sxorg;
00260 bx= qMin( x, sx );
00261 count = 1;
00262 }
00263 QString textDraw;
00264 if ( (*it) == textWords.last() ) {
00265 textDraw = (*it);
00266 }
00267 else {
00268 textDraw = (*it) + ' ';
00269 }
00270
00271 if ( count == 1 ) boffset = QABS( int( m_shadowDistanceX ) );
00272 else boffset = 0;
00273
00274 if ( bx < xend && (bx + fm2.width( textDraw ) + boffset ) < xend && ( qMin( y, sy ) - fm2.ascent() ) < ( qMin( yorg, syorg ) - fm2.ascent() + fm2.height() + QABS( m_shadowDistanceY ) ) ) {
00275 p->fillRect( bx, qMin( yorg, syorg ) - fm2.ascent() + fm2.height() + QABS( int( m_shadowDistanceY ) ), fm2.width( textDraw ) + boffset , fm2.height() + QABS( int( m_shadowDistanceY ) ) - ( qMin( yorg, syorg ) - qMin( y, sy ) + fm2.height() + QABS( int( m_shadowDistanceY ) ) ), m_backgroundColor );
00276 }
00277 else if ( bx < xend && (bx + fm2.width( textDraw ) + boffset ) >= xend && ( qMin( y, sy ) - fm2.ascent() ) < ( qMin( yorg, syorg ) - fm2.ascent() + fm2.height() + QABS( m_shadowDistanceY ) ) ) {
00278 p->fillRect( bx, qMin( yorg, syorg ) - fm2.ascent() + fm2.height() + QABS( int( m_shadowDistanceY ) ), xend - bx , fm2.height() + QABS( int( m_shadowDistanceY ) ) - ( qMin( yorg, syorg ) - qMin( y, sy ) + fm2.height() + QABS( int( m_shadowDistanceY ) ) ), m_backgroundColor );
00279 p->fillRect( xend, qMin( y, sy ) - fm2.ascent(), fm2.width( textDraw ) + boffset - xend + bx, fm2.height() + QABS( int( m_shadowDistanceY ) ), m_backgroundColor );
00280 }
00281 else {
00282 p->fillRect( bx, qMin( y, sy ) - fm2.ascent(), fm2.width( textDraw ) + boffset , fm2.height() + QABS( int( m_shadowDistanceY ) ), m_backgroundColor );
00283 }
00284
00285 if ( count == 1 ) boffset = QABS( int( m_shadowDistanceX ) );
00286 else boffset = 0;
00287 bx += fm2.width( textDraw ) + boffset;
00288
00289 if ( m_shadowDistanceX || m_shadowDistanceY )
00290 {
00291 p->save();
00292 p->setPen( m_shadowColor );
00293 p->drawText( sx, sy, textDraw );
00294 p->restore();
00295 }
00296
00297 p->drawText( x, y, textDraw );
00298
00299 switch ( m_underlining ) {
00300 case KoTextFormat::U_NONE:
00301 break;
00302 case KoTextFormat::U_SIMPLE:
00303 yUnderline = y + fm2.descent();
00304 ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
00305 thicknessUnderline = 1;
00306 drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
00307 break;
00308 case KoTextFormat::U_DOUBLE:
00309 yUnderline = y + fm2.descent();
00310 ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
00311 thicknessUnderline = 1;
00312 drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
00313 yUnderline = y + qRound( fm2.descent() / 2 );
00314 drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
00315 break;
00316 case KoTextFormat::U_SIMPLE_BOLD:
00317 yUnderline = y + fm2.descent();
00318 ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
00319 thicknessUnderline = qRound( displayFont.pointSize() / 10 ) + 1;
00320 drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
00321 break;
00322 case KoTextFormat::U_WAVE:
00323 yUnderline = y + fm2.descent();
00324 ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
00325 thicknessUnderline = 1;
00326 drawUnderlineWave( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
00327 break;
00328 default:
00329 break;
00330 }
00331
00332 switch ( m_strikethrough ) {
00333 case KoTextFormat::S_NONE:
00334 break;
00335 case KoTextFormat::S_SIMPLE:
00336 yStrikethrough = y - qRound( fm2.ascent() / 3 );
00337 ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw );
00338 thicknessStrikethrough = 1;
00339 drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
00340 break;
00341 case KoTextFormat::S_DOUBLE:
00342 yStrikethrough = y - qRound( fm2.ascent() / 4 );
00343 ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw );
00344 thicknessStrikethrough = 1;
00345 drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
00346 yStrikethrough = y - 2 * qRound( fm2.ascent() / 4 );
00347 drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
00348 break;
00349 case KoTextFormat::S_SIMPLE_BOLD:
00350 yStrikethrough = y - qRound( fm2.ascent() / 3 );
00351 ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw );
00352 thicknessStrikethrough = qRound( displayFont.pointSize() / 10 ) + 1;
00353 drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
00354 break;
00355 default:
00356 break;
00357 }
00358 x += fm2.width( textDraw );
00359 sx += fm2.width( textDraw );
00360 count++;
00361 }
00362
00363 p->restore();
00364 }
00365
00366 void KoFontDiaPreview::drawUnderline( int x, int y, int width, int thickness, QColor & color, QPainter *p )
00367 {
00368 p->save();
00369 switch ( m_underliningStyle ) {
00370 case KoTextFormat::U_SOLID:
00371 p->setPen( QPen( color, thickness, Qt::SolidLine ) );
00372 break;
00373 case KoTextFormat::U_DASH:
00374 p->setPen( QPen( color, thickness, Qt::DashLine ) );
00375 break;
00376 case KoTextFormat::U_DOT:
00377 p->setPen( QPen( color, thickness, Qt::DotLine ) );
00378 break;
00379 case KoTextFormat::U_DASH_DOT:
00380 p->setPen( QPen( color, thickness, Qt::DashDotLine ) );
00381 break;
00382 case KoTextFormat::U_DASH_DOT_DOT:
00383 p->setPen( QPen( color, thickness, Qt::DashDotDotLine ) );
00384 break;
00385 default:
00386 p->setPen( QPen( color, thickness, Qt::SolidLine ) );
00387 }
00388 p->drawLine( x, y, x+ width, y );
00389 p->restore();
00390 }
00391
00392 void KoFontDiaPreview::drawUnderlineWave( int x, int y, int width, int thickness, QColor & color, QPainter *p )
00393 {
00394 p->save();
00395 int offset = 2 * thickness;
00396 QPen pen(color, thickness, Qt::SolidLine);
00397 pen.setCapStyle(Qt::RoundCap);
00398 p->setPen(pen);
00399 double anc=acos(1.0-2*(static_cast<double>(offset-(x)%offset)/static_cast<double>(offset)))/3.1415*180;
00400 int pos=1;
00401
00402 if(2*((x/offset)/2)==x/offset)
00403 pos*=-1;
00404
00405 p->drawArc( (x/offset)*offset, y, offset, offset, 0, -qRound(pos*anc*16) );
00406
00407 int zigzag_x = (x/offset+1)*offset;
00408 for ( ; zigzag_x + offset <= width+x; zigzag_x += offset)
00409 {
00410 p->drawArc( zigzag_x, y, offset, offset, 0, pos*180*16 );
00411 pos*=-1;
00412 }
00413
00414 anc=acos(1.0-2*(static_cast<double>((x+width)%offset)/static_cast<double>(offset)))/3.1415*180;
00415 p->drawArc( zigzag_x, y, offset, offset, 180*16, -qRound(pos*anc*16) );
00416 p->restore();
00417 }
00418
00419 void KoFontDiaPreview::drawStrikethrough( int x, int y, int width, int thickness, QPainter *p )
00420 {
00421 p->save();
00422 switch ( m_strikethroughStyle ) {
00423 case KoTextFormat::S_SOLID:
00424 p->setPen( QPen( Qt::black, thickness, Qt::SolidLine ) );
00425 break;
00426 case KoTextFormat::S_DASH:
00427 p->setPen( QPen( Qt::black, thickness, Qt::DashLine ) );
00428 break;
00429 case KoTextFormat::S_DOT:
00430 p->setPen( QPen( Qt::black, thickness, Qt::DotLine ) );
00431 break;
00432 case KoTextFormat::S_DASH_DOT:
00433 p->setPen( QPen( Qt::black, thickness, Qt::DashDotLine ) );
00434 break;
00435 case KoTextFormat::S_DASH_DOT_DOT:
00436 p->setPen( QPen( Qt::black, thickness, Qt::DashDotDotLine ) );
00437 break;
00438 default:
00439 p->setPen( QPen( Qt::black, thickness, Qt::SolidLine ) );
00440 }
00441 p->drawLine( x, y, x+ width, y );
00442 p->restore();
00443 }
00444