/* This file is part of the KDE project Copyright (C) 2001, 2002 Montel Laurent 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 #include #include #include #include #include #include #include #include #include "KoFontDiaPreview.moc" KoFontDiaPreview::KoFontDiaPreview( TQWidget* tqparent, const char* name , WFlags fl ) : TQFrame( tqparent, 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( TQt::black ) ,m_backgroundColor( TQt::white ) ,m_shadowDistanceX( 0 ) ,m_shadowDistanceY( 0 ) ,m_shadowColor( TQt::black ) ,m_underlining( 0 ) ,m_underliningStyle( 0 ) ,m_underliningColor( TQt::black ) ,m_wordByWord( false ) ,m_strikethrough( 0 ) ,m_strikethroughStyle( 0 ) ,m_capitalisation( 0 ) ,m_subSuper( 0 ) ,m_offset( 0 ) ,m_relativeSize( 1 ) { setFrameStyle( TQFrame::WinPanel | TQFrame::Plain ); setBackgroundMode( PaletteBase ); setBackgroundColor( TQt::white ); setMinimumSize( 400, 100 ); } KoFontDiaPreview::~KoFontDiaPreview() { } void KoFontDiaPreview::setText( const TQString &text ) { m_text = text; update(); } void KoFontDiaPreview::setFont( const TQFont &font ) { m_font = font; m_fontSize = m_font.pointSize(); update(); } void KoFontDiaPreview::setFontColor( const TQColor &textColor ) { m_textColor = textColor; update(); } void KoFontDiaPreview::setBackgroundColor( const TQColor &backgroundColor ) { m_backgroundColor = backgroundColor; update(); } void KoFontDiaPreview::setShadow( double sdx, double sdy, TQColor shadowColor ) { m_shadowDistanceX = sdx; m_shadowDistanceY = sdy; m_shadowColor = shadowColor; update(); } void KoFontDiaPreview::setUnderlining( int underlining, int underliningStyle, const TQColor 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(); } TQString KoFontDiaPreview::formatCapitalisation( const TQString &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( TQPainter* p ) { p->save(); // sort out the font to use //Capitalisation double capitalisationCoeff; TQFontMetrics 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 TQFontMetrics fm( displayFont ); TQRect br = fm.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), TQt::AlignCenter | TQt::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 ); } TQFontMetrics fm1( displayFont ); br = fm1.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), TQt::AlignCenter | TQt::WordBreak, displayText ); int xorg = tqRound( ( 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; } TQFontMetrics fm2( displayFont ); br = fm2.boundingRect( contentsRect().x(), contentsRect().y(), contentsRect().width(), contentsRect().height(), TQt::AlignCenter | TQt::WordBreak, displayText ); int yorg = tqRound( ( contentsRect().height() - br.height() ) / 2 ) + fm1.ascent() + subSuperOffset; int sxorg = xorg + int( m_shadowDistanceX ); int syorg = yorg + int( m_shadowDistanceY ); TQStringList textWords = TQStringList::split( " ", displayText ); int x = xorg; int y = yorg; int sx = sxorg; int sy = syorg; int bx= TQMIN( 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 ( TQStringList::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= TQMIN( x, sx ); count = 1; } TQString textDraw; if ( (*it) == textWords.last() ) { textDraw = (*it); } else { textDraw = (*it) + " "; } /*background*/ if ( count == 1 ) boffset = TQABS( int( m_shadowDistanceX ) ); else boffset = 0; if ( bx < xend && (bx + fm2.width( textDraw ) + boffset ) < xend && ( TQMIN( y, sy ) - fm2.ascent() ) < ( TQMIN( yorg, syorg ) - fm2.ascent() + fm2.height() + TQABS( m_shadowDistanceY ) ) ) { p->fillRect( bx, TQMIN( yorg, syorg ) - fm2.ascent() + fm2.height() + TQABS( int( m_shadowDistanceY ) ), fm2.width( textDraw ) + boffset , fm2.height() + TQABS( int( m_shadowDistanceY ) ) - ( TQMIN( yorg, syorg ) - TQMIN( y, sy ) + fm2.height() + TQABS( int( m_shadowDistanceY ) ) ), m_backgroundColor ); } else if ( bx < xend && (bx + fm2.width( textDraw ) + boffset ) >= xend && ( TQMIN( y, sy ) - fm2.ascent() ) < ( TQMIN( yorg, syorg ) - fm2.ascent() + fm2.height() + TQABS( m_shadowDistanceY ) ) ) { p->fillRect( bx, TQMIN( yorg, syorg ) - fm2.ascent() + fm2.height() + TQABS( int( m_shadowDistanceY ) ), xend - bx , fm2.height() + TQABS( int( m_shadowDistanceY ) ) - ( TQMIN( yorg, syorg ) - TQMIN( y, sy ) + fm2.height() + TQABS( int( m_shadowDistanceY ) ) ), m_backgroundColor ); p->fillRect( xend, TQMIN( y, sy ) - fm2.ascent(), fm2.width( textDraw ) + boffset - xend + bx, fm2.height() + TQABS( int( m_shadowDistanceY ) ), m_backgroundColor ); } else { p->fillRect( bx, TQMIN( y, sy ) - fm2.ascent(), fm2.width( textDraw ) + boffset , fm2.height() + TQABS( int( m_shadowDistanceY ) ), m_backgroundColor ); } if ( count == 1 ) boffset = TQABS( int( m_shadowDistanceX ) ); else boffset = 0; bx += fm2.width( textDraw ) + boffset;//( count == 1 )?0:0;//TQABS( 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 + tqRound( 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 = tqRound( 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 - tqRound( 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 - tqRound( fm2.ascent() / 4 ); ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw ); thicknessStrikethrough = 1; drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p ); yStrikethrough = y - 2 * tqRound( fm2.ascent() / 4 ); drawStrikethrough( x, yStrikethrough, widthStrikethrough, thicknessStrikethrough, p ); break; case KoTextFormat::S_SIMPLE_BOLD: yStrikethrough = y - tqRound( fm2.ascent() / 3 ); ( m_wordByWord )? widthStrikethrough = fm2.width( (*it) ): widthStrikethrough = fm2.width( textDraw ); thicknessStrikethrough = tqRound( 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, TQColor & color, TQPainter *p ) { p->save(); switch ( m_underliningStyle ) { case KoTextFormat::U_SOLID: p->setPen( TQPen( color, thickness, TQt::SolidLine ) ); break; case KoTextFormat::U_DASH: p->setPen( TQPen( color, thickness, TQt::DashLine ) ); break; case KoTextFormat::U_DOT: p->setPen( TQPen( color, thickness, TQt::DotLine ) ); break; case KoTextFormat::U_DASH_DOT: p->setPen( TQPen( color, thickness, TQt::DashDotLine ) ); break; case KoTextFormat::U_DASH_DOT_DOT: p->setPen( TQPen( color, thickness, TQt::DashDotDotLine ) ); break; default: p->setPen( TQPen( color, thickness, TQt::SolidLine ) ); } p->drawLine( x, y, x+ width, y ); p->restore(); } void KoFontDiaPreview::drawUnderlineWave( int x, int y, int width, int thickness, TQColor & color, TQPainter *p ) { p->save(); int offset = 2 * thickness; TQPen pen(color, thickness, TQt::SolidLine); pen.setCapStyle(Qt::RoundCap); p->setPen(pen); double anc=acos(1.0-2*(static_cast(offset-(x)%offset)/static_cast(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, -tqRound(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((x+width)%offset)/static_cast(offset)))/3.1415*180; p->drawArc( zigzag_x, y, offset, offset, 180*16, -tqRound(pos*anc*16) ); p->restore(); } void KoFontDiaPreview::drawStrikethrough( int x, int y, int width, int thickness, TQPainter *p ) { p->save(); switch ( m_strikethroughStyle ) { case KoTextFormat::S_SOLID: p->setPen( TQPen( TQt::black, thickness, TQt::SolidLine ) ); break; case KoTextFormat::S_DASH: p->setPen( TQPen( TQt::black, thickness, TQt::DashLine ) ); break; case KoTextFormat::S_DOT: p->setPen( TQPen( TQt::black, thickness, TQt::DotLine ) ); break; case KoTextFormat::S_DASH_DOT: p->setPen( TQPen( TQt::black, thickness, TQt::DashDotLine ) ); break; case KoTextFormat::S_DASH_DOT_DOT: p->setPen( TQPen( TQt::black, thickness, TQt::DashDotDotLine ) ); break; default: p->setPen( TQPen( TQt::black, thickness, TQt::SolidLine ) ); } p->drawLine( x, y, x+ width, y ); p->restore(); }