lib

KoFontDiaPreview.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C)  2001, 2002 Montel Laurent <lmontel@mandrakesoft.com>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
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     // sort out the font to use
00162 
00163     //Capitalisation
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     //Set the display font. m_font is untouched by the modifications of capitalisation
00186     displayFont = m_font;
00187     displayFont.setPointSizeFloat( m_font.pointSize() * capitalisationCoeff );
00188 
00189 // format the string in case Small Caps
00190     displayText = formatCapitalisation( m_text );
00191 
00192 // draw the stuff
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     // sub / superscript modifications
00207     int subSuperOffset = 0;
00208     switch ( m_subSuper ) {
00209         case 0: //normal
00210             displayFont.setPointSizeFloat( displayFont.pointSize() * m_relativeSize );
00211             subSuperOffset = -( m_offset );
00212             break;
00213         case 1: //subscript
00214             displayFont.setPointSizeFloat( displayFont.pointSize() * m_relativeSize );
00215             subSuperOffset = fm1.height() / 6;
00216             break;
00217         case 2: //superscript
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 /*background*/
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;//( count == 1 )?0:0;//QABS( m_shadowDistanceX ):0;
00286 /*shadow*/
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 /*text*/    
00295         p->drawText( x, y, textDraw );
00296 /*underline*/   
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 /*Strikethrough*/
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     //set starting position
00400     if(2*((x/offset)/2)==x/offset)
00401         pos*=-1;
00402     //draw first part of wave
00403     p->drawArc( (x/offset)*offset, y, offset, offset, 0, -qRound(pos*anc*16) );
00404     //now the main part
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     //and here we finish
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 
KDE Home | KDE Accessibility Home | Description of Access Keys