F:/KPlato/koffice/libs/kotext/KoBorder.cpp

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2000, 2001 Thomas Zander <zander@kde.org>
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 "KoBorder.h"
00021 #include <qdom.h>
00022 #include <QByteArray>
00023 #include <kdebug.h>
00024 #include "KoZoomHandler.h"
00025 #include "KoTextFormat.h"
00026 #include "KoRichText.h" // for KoTextFormat
00027 #include "KoTextParag.h"
00028 #include "KoUnit.h"
00029 #include <float.h>
00030 
00031 static const struct BorderStyle {
00032     Qt::PenStyle penStyle;
00033     QByteArray oasisName;
00034     QByteArray uiStringStyle;
00035 } s_borderStyles[] = {
00036     { Qt::SolidLine, "solid", "_________" }, // SOLID
00037     { Qt::DashLine, "dashed", "___ ___ __" }, // DASH
00038     { Qt::DotLine, "dotted", "_ _ _ _ _ _" }, // DOT
00039     { Qt::DashDotLine, "dot-dash", "___ _ ___ _" }, // DASH_DOT
00040     { Qt::DashDotDotLine, "dot-dot-dash", "___ _ _ ___" }, // DASH_DOT_DOT
00041     { Qt::SolidLine, "double", "===========" } // DOUBLE_LINE
00042 };
00043 
00044 KoBorder::KoBorder()
00045     : color(), m_style( SOLID )
00046 {
00047     setPenWidth( 1 );
00048 }
00049 
00050 KoBorder::KoBorder( const QColor & c, BorderStyle s, double width )
00051     : color( c ), m_style( s )
00052 {
00053     setPenWidth( width );
00054 }
00055 
00056 bool KoBorder::operator==( const KoBorder _brd ) const {
00057     return ( m_style == _brd.m_style && color == _brd.color && ptPenWidth == _brd.ptPenWidth );
00058 }
00059 
00060 bool KoBorder::operator!=( const KoBorder _brd ) const {
00061     return ( m_style != _brd.m_style || color != _brd.color || ptPenWidth != _brd.ptPenWidth );
00062 }
00063 
00064 void KoBorder::setStyle(BorderStyle _style)
00065 {
00066     m_style = _style;
00067     setPenWidth( ptPenWidth );
00068 }
00069 
00070 void KoBorder::setPenWidth(double _w)
00071 {
00072     ptPenWidth = _w;
00073     if ( m_style == KoBorder::DOUBLE_LINE && _w > 0 )
00074         ptWidth = 2 * ptPenWidth + 1;
00075     else
00076         ptWidth = _w;
00077 }
00078 
00079 QPen KoBorder::borderPen( const KoBorder & _brd, int width, QColor defaultColor )
00080 {
00081     QPen pen( _brd.color, width );
00082     if ( !_brd.color.isValid() )
00083         pen.setColor( defaultColor );
00084 
00085     pen.setStyle( s_borderStyles[ _brd.m_style ].penStyle );
00086 
00087     return pen;
00088 }
00089 
00090 // KOffice-1.3 file format (deprecated)
00091 KoBorder KoBorder::loadBorder( const QDomElement & elem )
00092 {
00093     KoBorder bd;
00094     if ( elem.hasAttribute("red") )
00095     {
00096         int r = elem.attribute("red").toInt();
00097         int g = elem.attribute("green").toInt();
00098         int b = elem.attribute("blue").toInt();
00099         bd.color.setRgb( r, g, b );
00100     }
00101     bd.m_style = static_cast<BorderStyle>( elem.attribute("style").toInt() );
00102     bd.setPenWidth( elem.attribute("width").toDouble() );
00103     return bd;
00104 }
00105 
00106 void KoBorder::loadFoBorder( const QString& border )
00107 {
00108     //string like "0.088cm solid #800000"
00109 
00110     if (border.isEmpty() || border=="none" || border=="hidden") { // in fact no border
00111         setPenWidth( 0 );
00112         return;
00113     }
00114 
00115     // ## isn't it faster to use QStringList::split than parse it 3 times?
00116     QString _width = border.section(' ', 0, 0);
00117     QByteArray _style = border.section(' ', 1, 1).toLatin1();
00118     QString _color = border.section(' ', 2, 2);
00119 
00120     //TODO: let the user choose a more precise border width (in the current unit)
00121     double const penWidth = KoUnit::parseValue( _width, 1.0 );
00122     //kDebug() << "penWidth:" << penWidth << endl;
00123     if ( penWidth < 1.5 )
00124         setPenWidth( 1.0 );
00125     else if ( penWidth < 2.5 )
00126         setPenWidth( 2.0 );
00127     else if ( penWidth < 3.5 )
00128         setPenWidth( 3.0 );
00129     else if ( penWidth < 4.5 )
00130         setPenWidth( 4.0 );
00131     else if ( penWidth < 5.5 )
00132         setPenWidth( 5.0 );
00133     else if ( penWidth < 6.5 )
00134         setPenWidth( 6.0 );
00135     else if ( penWidth < 7.5 )
00136         setPenWidth( 7.0 );
00137     else if ( penWidth < 8.5 )
00138         setPenWidth( 8.0 );
00139     else if ( penWidth < 9.5 )
00140         setPenWidth( 9.0 );
00141     else
00142         setPenWidth( 10.0 );
00143 
00144     m_style = SOLID;
00145     for ( uint i = 0; i < sizeof( s_borderStyles ) / sizeof *s_borderStyles; ++i ) {
00146         if ( _style == s_borderStyles[i].oasisName )
00147             m_style = static_cast<BorderStyle>( i );
00148     }
00149 
00150     if ( _color.isEmpty() )
00151         color = QColor();
00152     else
00153         color.setNamedColor( _color );
00154 }
00155 
00156 QString KoBorder::saveFoBorder() const
00157 {
00158     if ( QABS( ptPenWidth ) < 1E-10 ) // i.e. ptPenWidth == 0
00159         return "none";
00160     //string like "2pt solid #800000"
00161     QString str = QString::number( ptPenWidth, 'g', DBL_DIG );
00162     str += "pt ";
00163     str += s_borderStyles[ m_style ].oasisName;
00164     if ( color.isValid() ) {
00165         str += ' ';
00166         str += color.name();
00167     }
00168     return str;
00169 }
00170 
00171 // KOffice-1.3 file format (deprecated)
00172 void KoBorder::save( QDomElement & elem ) const
00173 {
00174     if (color.isValid()) {
00175         elem.setAttribute("red", color.red());
00176         elem.setAttribute("green", color.green());
00177         elem.setAttribute("blue", color.blue());
00178     }
00179     elem.setAttribute("style", static_cast<int>( m_style ));
00180     elem.setAttribute("width", ptPenWidth);
00181 }
00182 
00183 KoBorder::BorderStyle KoBorder::getStyle( const QString &style )
00184 {
00185     for ( uint i = 0; i < sizeof( s_borderStyles ) / sizeof *s_borderStyles; ++i ) {
00186         if ( style == s_borderStyles[i].uiStringStyle.data() )
00187             return static_cast<BorderStyle>( i );
00188     }
00189     // default
00190     return KoBorder::SOLID;
00191 }
00192 
00193 QString KoBorder::getStyle( const BorderStyle &style )
00194 {
00195     return s_borderStyles[style].uiStringStyle;
00196 }
00197 
00198 int KoBorder::zoomWidthX( double ptWidth, KoZoomHandler * zoomHandler, int minborder )
00199 {
00200     // If a border was set, then zoom it and apply a minimum of 1, so that it's always visible.
00201     // If no border was set, apply minborder ( 0 for paragraphs, 1 for frames )
00202     return ptWidth > 0 ? qMax( 1, zoomHandler->zoomItXOld( ptWidth ) /*applies qRound*/ ) : minborder;
00203 }
00204 
00205 int KoBorder::zoomWidthY( double ptWidth, KoZoomHandler * zoomHandler, int minborder )
00206 {
00207     // If a border was set, then zoom it and apply a minimum of 1, so that it's always visible.
00208     // If no border was set, apply minborder ( 0 for paragraphs, 1 for frames )
00209     return ptWidth > 0 ? qMax( 1, zoomHandler->zoomItYOld( ptWidth ) /*applies qRound*/ ) : minborder;
00210 }
00211 
00212 void KoBorder::drawBorders( QPainter& painter, KoZoomHandler * zoomHandler, const QRect& rect, const KoBorder& leftBorder, const KoBorder& rightBorder, const KoBorder& topBorder, const KoBorder& bottomBorder, int minborder, const QPen& defaultPen, bool drawTopBorder /* = true */, bool drawBottomBorder /* = true */)
00213 {
00214     int topBorderWidth = zoomWidthY( topBorder.width(), zoomHandler, minborder );
00215     int bottomBorderWidth = zoomWidthY( bottomBorder.width(), zoomHandler, minborder );
00216     int leftBorderWidth = zoomWidthX( leftBorder.width(), zoomHandler, minborder );
00217     int rightBorderWidth = zoomWidthX( rightBorder.width(), zoomHandler, minborder );
00218 
00219     int topBorderPenWidth = zoomWidthY( topBorder.penWidth(), zoomHandler, minborder );
00220     int bottomBorderPenWidth = zoomWidthY( bottomBorder.penWidth(), zoomHandler, minborder );
00221     int leftBorderPenWidth = zoomWidthX( leftBorder.penWidth(), zoomHandler, minborder );
00222     int rightBorderPenWidth = zoomWidthX( rightBorder.penWidth(), zoomHandler, minborder );
00223 
00224     // Wide pen don't draw the last pixel, so add one to the bottom and right coords
00225     int lastPixelAdj = 1;
00226 
00227     //kDebug(32500) << "KoBorder::drawBorders widths: top=" << topBorderWidth << " bottom=" << bottomBorderWidth
00228     //               << " left=" << leftBorderWidth << " right=" << rightBorderWidth << endl;
00229 
00230     //kDebug(32500) << "                   penWidths: top=" << topBorderPenWidth << " bottom=" << bottomBorderPenWidth
00231     //               << " left=" << leftBorderPenWidth << " right=" << rightBorderPenWidth << endl;
00232 
00233     QColor defaultColor = KoTextFormat::defaultTextColor( &painter );
00234 
00235     if ( topBorderWidth > 0 && drawTopBorder )
00236     {
00237         if ( topBorder.penWidth() > 0 )
00238             painter.setPen( KoBorder::borderPen( topBorder, topBorderPenWidth, defaultColor ) );
00239         else
00240             painter.setPen( defaultPen );
00241         int y = rect.top() - topBorderWidth + topBorderPenWidth/2;
00242         if ( topBorder.m_style==KoBorder::DOUBLE_LINE)
00243         {
00244             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+2*(rightBorderPenWidth+lastPixelAdj), y );
00245             y += topBorderPenWidth + 1;
00246             painter.drawLine( rect.left()-leftBorderPenWidth, y, rect.right()+rightBorderPenWidth+lastPixelAdj, y );
00247         }
00248         else
00249         {
00250             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+rightBorderWidth+lastPixelAdj, y );
00251         }
00252     }
00253     if ( bottomBorderWidth > 0 && drawBottomBorder )
00254     {
00255         if ( bottomBorder.penWidth() > 0 )
00256             painter.setPen( KoBorder::borderPen( bottomBorder, bottomBorderPenWidth, defaultColor ) );
00257         else
00258             painter.setPen( defaultPen );
00259         //kDebug(32500) << "bottomBorderWidth=" << bottomBorderWidth << " bottomBorderWidth/2=" << (int)bottomBorderWidth/2 << endl;
00260         int y = rect.bottom() + bottomBorderPenWidth/2 + 1;
00261         //kDebug(32500) << "   -> bottom=" << rect.bottom() << " y=" << y << endl;
00262         if ( bottomBorder.m_style==KoBorder::DOUBLE_LINE)
00263         {
00264             painter.drawLine( rect.left()-leftBorderPenWidth, y, rect.right()+rightBorderPenWidth+lastPixelAdj, y );
00265             y += bottomBorderPenWidth + 1;
00266             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+2*(rightBorderPenWidth+lastPixelAdj), y );
00267         }
00268         else
00269         {
00270             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+rightBorderWidth+lastPixelAdj, y );
00271         }
00272     }
00273     if ( leftBorderWidth > 0 )
00274     {
00275         if ( leftBorder.penWidth() > 0 )
00276             painter.setPen( KoBorder::borderPen( leftBorder, leftBorderPenWidth, defaultColor ) );
00277         else
00278             painter.setPen( defaultPen );
00279         int x = rect.left() - leftBorderWidth + leftBorderPenWidth/2;
00280         if ( leftBorder.m_style==KoBorder::DOUBLE_LINE)
00281         {
00282             painter.drawLine( x, rect.top()-topBorderWidth, x, rect.bottom()+2*(bottomBorderPenWidth+lastPixelAdj) );
00283             x += leftBorderPenWidth + 1;
00284             painter.drawLine( x, rect.top()-topBorderPenWidth, x, rect.bottom()+bottomBorderPenWidth+lastPixelAdj );
00285         }
00286         else
00287         {
00288             int yTop = rect.top() - topBorderWidth;
00289             int yBottom = rect.bottom() + bottomBorderWidth;
00290             /*kDebug(32500) << " pen=" << painter.pen() << " rect=" << rect << " topBorderWidth=" << topBorderWidth
00291                            << " painting from " << x << "," << yTop
00292                            << " to " << x << "," << yBottom << endl;*/
00293             painter.drawLine( x, yTop, x, yBottom+lastPixelAdj );
00294         }
00295     }
00296     if ( rightBorderWidth > 0 )
00297     {
00298         if ( rightBorder.penWidth() > 0 )
00299             painter.setPen( KoBorder::borderPen( rightBorder, rightBorderPenWidth, defaultColor ) );
00300         else
00301             painter.setPen( defaultPen );
00302         int x = rect.right() + rightBorderPenWidth/2 + 1;
00303         if ( rightBorder.m_style==KoBorder::DOUBLE_LINE)
00304         {
00305             painter.drawLine( x, rect.top()-topBorderPenWidth, x, rect.bottom()+bottomBorderPenWidth+lastPixelAdj );
00306             x += rightBorderPenWidth + 1;
00307             painter.drawLine( x, rect.top()-topBorderWidth, x, rect.bottom()+2*(bottomBorderPenWidth+lastPixelAdj) );
00308 
00309         }
00310         else
00311         {
00312             int yTop = rect.top()-topBorderWidth;
00313             int yBottom = rect.bottom()+bottomBorderWidth+lastPixelAdj;
00314             /*kDebug(32500) << " pen=" << painter.pen() << " rect=" << rect << " topBorderWidth=" << topBorderWidth
00315                            << " painting from " << x << "," << yTop
00316                            << " to " << x << "," << yBottom << endl;*/
00317             painter.drawLine( x, yTop, x, yBottom );
00318         }
00319     }
00320 }

Généré le Wed Nov 22 23:41:07 2006 pour KPlato par  doxygen 1.5.1-p1