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