summaryrefslogtreecommitdiffstats
path: root/lib/kotext/KoFontDiaPreview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kotext/KoFontDiaPreview.cpp')
-rw-r--r--lib/kotext/KoFontDiaPreview.cpp442
1 files changed, 442 insertions, 0 deletions
diff --git a/lib/kotext/KoFontDiaPreview.cpp b/lib/kotext/KoFontDiaPreview.cpp
new file mode 100644
index 000000000..32473e430
--- /dev/null
+++ b/lib/kotext/KoFontDiaPreview.cpp
@@ -0,0 +1,442 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KoFontDiaPreview.h"
+#include "KoGlobal.h"
+#include "KoTextFormat.h"
+
+#include <klocale.h>
+
+#include <qfontmetrics.h>
+#include <qrect.h>
+#include <qpainter.h>
+#include <qfont.h>
+#include <qstringlist.h>
+#include <qstring.h>
+#include <qregexp.h>
+
+#include <math.h>
+
+#include "KoFontDiaPreview.moc"
+
+KoFontDiaPreview::KoFontDiaPreview( QWidget* parent, const char* name , WFlags fl )
+ : QFrame( parent, name, fl )
+ ,m_text( i18n( "The quick brown dog jumps over the lazy cat." ) )
+ ,displayText( i18n( "The quick brown dog jumps over the lazy cat." ) )
+ ,m_font( KoGlobal::defaultFont() )
+ ,m_textColor( Qt::black )
+ ,m_backgroundColor( Qt::white )
+ ,m_shadowDistanceX( 0 )
+ ,m_shadowDistanceY( 0 )
+ ,m_shadowColor( Qt::black )
+ ,m_underlining( 0 )
+ ,m_underliningStyle( 0 )
+ ,m_underliningColor( Qt::black )
+ ,m_wordByWord( false )
+ ,m_strikethrough( 0 )
+ ,m_strikethroughStyle( 0 )
+ ,m_capitalisation( 0 )
+ ,m_subSuper( 0 )
+ ,m_offset( 0 )
+ ,m_relativeSize( 1 )
+
+{
+ setFrameStyle( QFrame::WinPanel | QFrame::Plain );
+ setBackgroundMode( PaletteBase );
+ setBackgroundColor( Qt::white );
+ setMinimumSize( 400, 100 );
+}
+
+KoFontDiaPreview::~KoFontDiaPreview()
+{
+}
+
+void KoFontDiaPreview::setText( const QString &text )
+{
+ m_text = text;
+ update();
+}
+
+void KoFontDiaPreview::setFont( const QFont &font )
+{
+ m_font = font;
+ m_fontSize = m_font.pointSize();
+ update();
+}
+
+void KoFontDiaPreview::setFontColor( const QColor &textColor )
+{
+ m_textColor = textColor;
+ update();
+}
+
+void KoFontDiaPreview::setBackgroundColor( const QColor &backgroundColor )
+{
+ m_backgroundColor = backgroundColor;
+ update();
+}
+
+void KoFontDiaPreview::setShadow( double sdx, double sdy, QColor shadowColor )
+{
+ m_shadowDistanceX = sdx;
+ m_shadowDistanceY = sdy;
+ m_shadowColor = shadowColor;
+ update();
+}
+
+void KoFontDiaPreview::setUnderlining( int underlining, int underliningStyle, const QColor underliningColor, bool wordByWord )
+{
+ m_underlining = underlining;
+ m_underliningStyle = underliningStyle;
+ m_underliningColor = underliningColor;
+ m_wordByWord = wordByWord;
+ update();
+}
+
+void KoFontDiaPreview::setWordByWord( bool wordByWord )
+{
+ m_wordByWord = wordByWord;
+ update();
+}
+
+void KoFontDiaPreview::setStrikethrough( int strikethrough, int strikethroughStyle, bool wordByWord )
+{
+ m_strikethrough = strikethrough;
+ m_strikethroughStyle = strikethroughStyle;
+ m_wordByWord = wordByWord;
+ update();
+}
+
+void KoFontDiaPreview::setCapitalisation( int capitalisation )
+{
+ m_capitalisation = capitalisation;
+ update();
+}
+
+void KoFontDiaPreview::setSubSuperscript( int subSuper, int offset, double relativeSize )
+{
+ m_subSuper = subSuper;
+ m_offset = offset;
+ m_relativeSize = relativeSize;
+ update();
+}
+
+QString KoFontDiaPreview::formatCapitalisation( const QString &string )
+{
+ switch ( m_capitalisation )
+ {
+ case KoTextFormat::ATT_NONE :
+ return string;
+ case KoTextFormat::ATT_UPPER :
+ return string.upper();
+ case KoTextFormat::ATT_LOWER :
+ return string.lower();
+ case KoTextFormat::ATT_SMALL_CAPS :
+ return string.upper();
+ default:
+ return string;
+ }
+}
+
+void KoFontDiaPreview::drawContents( QPainter* p )
+{
+ p->save();
+
+ // sort out the font to use
+
+ //Capitalisation
+ double capitalisationCoeff;
+ QFontMetrics fmCapitalisation( m_font );
+
+ switch ( m_capitalisation )
+ {
+ case KoTextFormat::ATT_NONE :
+ capitalisationCoeff = 1.0;
+ break;
+ case KoTextFormat::ATT_UPPER :
+ capitalisationCoeff = 1.0;
+ break;
+ case KoTextFormat::ATT_LOWER :
+ capitalisationCoeff = 1.0;
+ break;
+ case KoTextFormat::ATT_SMALL_CAPS :
+ capitalisationCoeff = ((double)fmCapitalisation.boundingRect("x").height()/(double)fmCapitalisation.boundingRect("X").height());
+ break;
+ default:
+ capitalisationCoeff = 1.0;
+ break;
+ }
+ //Set the display font. m_font is untouched by the modifications of capitalisation
+ displayFont = m_font;
+ displayFont.setPointSizeFloat( m_font.pointSize() * capitalisationCoeff );
+
+// format the string in case Small Caps
+ displayText = formatCapitalisation( m_text );
+
+// draw the stuff
+ QFontMetrics fm( displayFont );
+ QRect br = fm.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), Qt::AlignCenter | Qt::WordBreak, displayText );
+
+ if ( br.width() > contentsRect().width() || br.height() > contentsRect().height() ) {
+ displayText = formatCapitalisation( i18n( "Font too large for the preview pane" ) );
+ displayFont.setPointSizeFloat( 14 * capitalisationCoeff );
+ }
+
+ QFontMetrics fm1( displayFont );
+ br = fm1.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), Qt::AlignCenter | Qt::WordBreak, displayText );
+
+ int xorg = qRound( ( contentsRect().width() - br.width() ) / 2 ) + contentsRect().x() - fm1.leftBearing( displayText.at( 0 ) );
+
+ // sub / superscript modifications
+ int subSuperOffset = 0;
+ switch ( m_subSuper ) {
+ case 0: //normal
+ displayFont.setPointSizeFloat( displayFont.pointSize() * m_relativeSize );
+ subSuperOffset = -( m_offset );
+ break;
+ case 1: //subscript
+ displayFont.setPointSizeFloat( displayFont.pointSize() * m_relativeSize );
+ subSuperOffset = fm1.height() / 6;
+ break;
+ case 2: //superscript
+ displayFont.setPointSizeFloat( displayFont.pointSize() * m_relativeSize );
+ subSuperOffset = 0 - ( fm1.height() / 2 );
+ break;
+ default:
+ displayFont.setPointSizeFloat( displayFont.pointSize() * m_relativeSize );
+ subSuperOffset = 0 - m_offset;
+ break;
+ }
+
+ QFontMetrics fm2( displayFont );
+ br = fm2.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), Qt::AlignCenter | Qt::WordBreak, displayText );
+ int yorg = qRound( ( contentsRect().height() - br.height() ) / 2 ) + fm1.ascent() + subSuperOffset;
+ int sxorg = xorg + int( m_shadowDistanceX );
+ int syorg = yorg + int( m_shadowDistanceY );
+ QStringList textWords = QStringList::split( " ", displayText );
+ int x = xorg;
+ int y = yorg;
+ int sx = sxorg;
+ int sy = syorg;
+ int bx= QMIN( x, sx );
+ int xend = bx;
+ int yUnderline;
+ int widthUnderline;
+ int thicknessUnderline;
+ int yStrikethrough;
+ int widthStrikethrough;
+ int thicknessStrikethrough;
+
+ p->setFont(displayFont );
+ p->setPen( m_textColor );
+ int count = 1;
+
+ for ( QStringList::iterator it = textWords.begin(); it != textWords.end(); ++it ) {
+ int boffset = 0;
+ if ( x + fm2.width( (*it) ) > contentsRect().width() ) {
+ y += fm1.lineSpacing();
+ sy += fm1.lineSpacing();
+ xend = x;
+ x = xorg;
+ sx = sxorg;
+ bx= QMIN( x, sx );
+ count = 1;
+ }
+ QString textDraw;
+ if ( (*it) == textWords.last() ) {
+ textDraw = (*it);
+ }
+ else {
+ textDraw = (*it) + " ";
+ }
+/*background*/
+ if ( count == 1 ) boffset = QABS( int( m_shadowDistanceX ) );
+ else boffset = 0;
+
+ if ( bx < xend && (bx + fm2.width( textDraw ) + boffset ) < xend && ( QMIN( y, sy ) - fm2.ascent() ) < ( QMIN( yorg, syorg ) - fm2.ascent() + fm2.height() + QABS( m_shadowDistanceY ) ) ) {
+ 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 );
+ }
+ 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 ) ) ) {
+ 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 );
+ p->fillRect( xend, QMIN( y, sy ) - fm2.ascent(), fm2.width( textDraw ) + boffset - xend + bx, fm2.height() + QABS( int( m_shadowDistanceY ) ), m_backgroundColor );
+ }
+ else {
+ p->fillRect( bx, QMIN( y, sy ) - fm2.ascent(), fm2.width( textDraw ) + boffset , fm2.height() + QABS( int( m_shadowDistanceY ) ), m_backgroundColor );
+ }
+
+ if ( count == 1 ) boffset = QABS( int( m_shadowDistanceX ) );
+ else boffset = 0;
+ bx += fm2.width( textDraw ) + boffset;//( count == 1 )?0:0;//QABS( m_shadowDistanceX ):0;
+/*shadow*/
+ if ( m_shadowDistanceX || m_shadowDistanceY )
+ {
+ p->save();
+ p->setPen( m_shadowColor );
+ p->drawText( sx, sy, textDraw );
+ p->restore();
+ }
+/*text*/
+ p->drawText( x, y, textDraw );
+/*underline*/
+ switch ( m_underlining ) {
+ case KoTextFormat::U_NONE:
+ break;
+ case KoTextFormat::U_SIMPLE:
+ yUnderline = y + fm2.descent();
+ ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
+ thicknessUnderline = 1;
+ drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
+ break;
+ case KoTextFormat::U_DOUBLE:
+ yUnderline = y + fm2.descent();
+ ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
+ thicknessUnderline = 1;
+ drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
+ yUnderline = y + qRound( fm2.descent() / 2 );
+ drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
+ break;
+ case KoTextFormat::U_SIMPLE_BOLD:
+ yUnderline = y + fm2.descent();
+ ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
+ thicknessUnderline = qRound( displayFont.pointSize() / 10 ) + 1;
+ drawUnderline( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
+ break;
+ case KoTextFormat::U_WAVE:
+ yUnderline = y + fm2.descent();
+ ( m_wordByWord )? widthUnderline = fm2.width( (*it) ): widthUnderline = fm2.width( textDraw );
+ thicknessUnderline = 1;
+ drawUnderlineWave( x, yUnderline, widthUnderline, thicknessUnderline, m_underliningColor, p );
+ break;
+ default:
+ break;
+ }
+/*Strikethrough*/
+ switch ( m_strikethrough ) {
+ case KoTextFormat::S_NONE:
+ break;
+ case KoTextFormat::S_SIMPLE:
+ yStrikethrough = y - qRound( fm2.ascent() / 3 );
+ ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw );
+ thicknessStrikethrough = 1;
+ drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
+ break;
+ case KoTextFormat::S_DOUBLE:
+ yStrikethrough = y - qRound( fm2.ascent() / 4 );
+ ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw );
+ thicknessStrikethrough = 1;
+ drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
+ yStrikethrough = y - 2 * qRound( fm2.ascent() / 4 );
+ drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
+ break;
+ case KoTextFormat::S_SIMPLE_BOLD:
+ yStrikethrough = y - qRound( fm2.ascent() / 3 );
+ ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw );
+ thicknessStrikethrough = qRound( displayFont.pointSize() / 10 ) + 1;
+ drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p );
+ break;
+ default:
+ break;
+ }
+ x += fm2.width( textDraw );
+ sx += fm2.width( textDraw );
+ count++;
+ }
+
+ p->restore();
+}
+
+void KoFontDiaPreview::drawUnderline( int x, int y, int width, int thickness, QColor & color, QPainter *p )
+{
+ p->save();
+ switch ( m_underliningStyle ) {
+ case KoTextFormat::U_SOLID:
+ p->setPen( QPen( color, thickness, Qt::SolidLine ) );
+ break;
+ case KoTextFormat::U_DASH:
+ p->setPen( QPen( color, thickness, Qt::DashLine ) );
+ break;
+ case KoTextFormat::U_DOT:
+ p->setPen( QPen( color, thickness, Qt::DotLine ) );
+ break;
+ case KoTextFormat::U_DASH_DOT:
+ p->setPen( QPen( color, thickness, Qt::DashDotLine ) );
+ break;
+ case KoTextFormat::U_DASH_DOT_DOT:
+ p->setPen( QPen( color, thickness, Qt::DashDotDotLine ) );
+ break;
+ default:
+ p->setPen( QPen( color, thickness, Qt::SolidLine ) );
+ }
+ p->drawLine( x, y, x+ width, y );
+ p->restore();
+}
+
+void KoFontDiaPreview::drawUnderlineWave( int x, int y, int width, int thickness, QColor & color, QPainter *p )
+{
+ p->save();
+ int offset = 2 * thickness;
+ QPen pen(color, thickness, Qt::SolidLine);
+ pen.setCapStyle(Qt::RoundCap);
+ p->setPen(pen);
+ double anc=acos(1.0-2*(static_cast<double>(offset-(x)%offset)/static_cast<double>(offset)))/3.1415*180;
+ int pos=1;
+ //set starting position
+ if(2*((x/offset)/2)==x/offset)
+ pos*=-1;
+ //draw first part of wave
+ p->drawArc( (x/offset)*offset, y, offset, offset, 0, -qRound(pos*anc*16) );
+ //now the main part
+ int zigzag_x = (x/offset+1)*offset;
+ for ( ; zigzag_x + offset <= width+x; zigzag_x += offset)
+ {
+ p->drawArc( zigzag_x, y, offset, offset, 0, pos*180*16 );
+ pos*=-1;
+ }
+ //and here we finish
+ anc=acos(1.0-2*(static_cast<double>((x+width)%offset)/static_cast<double>(offset)))/3.1415*180;
+ p->drawArc( zigzag_x, y, offset, offset, 180*16, -qRound(pos*anc*16) );
+ p->restore();
+}
+
+void KoFontDiaPreview::drawStrikethrough( int x, int y, int width, int thickness, QPainter *p )
+{
+ p->save();
+ switch ( m_strikethroughStyle ) {
+ case KoTextFormat::S_SOLID:
+ p->setPen( QPen( Qt::black, thickness, Qt::SolidLine ) );
+ break;
+ case KoTextFormat::S_DASH:
+ p->setPen( QPen( Qt::black, thickness, Qt::DashLine ) );
+ break;
+ case KoTextFormat::S_DOT:
+ p->setPen( QPen( Qt::black, thickness, Qt::DotLine ) );
+ break;
+ case KoTextFormat::S_DASH_DOT:
+ p->setPen( QPen( Qt::black, thickness, Qt::DashDotLine ) );
+ break;
+ case KoTextFormat::S_DASH_DOT_DOT:
+ p->setPen( QPen( Qt::black, thickness, Qt::DashDotDotLine ) );
+ break;
+ default:
+ p->setPen( QPen( Qt::black, thickness, Qt::SolidLine ) );
+ }
+ p->drawLine( x, y, x+ width, y );
+ p->restore();
+}
+