qwt_text.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_text.h"
00011 #include "qwt_painter.h"
00012 #include "qwt_text_engine.h"
00013 #include <qmap.h>
00014 #include <qfont.h>
00015 #include <qcolor.h>
00016 #include <qpen.h>
00017 #include <qbrush.h>
00018 #include <qpainter.h>
00019 #include <qapplication.h>
00020 #include <qdesktopwidget.h>
00021 #include <qmath.h>
00022 
00023 class QwtTextEngineDict
00024 {
00025 public:
00026     static QwtTextEngineDict &dict();
00027 
00028     void setTextEngine( QwtText::TextFormat, QwtTextEngine * );
00029 
00030     const QwtTextEngine *textEngine( QwtText::TextFormat ) const;
00031     const QwtTextEngine *textEngine( const QString &,
00032         QwtText::TextFormat ) const;
00033 
00034 private:
00035     QwtTextEngineDict();
00036     ~QwtTextEngineDict();
00037 
00038     typedef QMap<int, QwtTextEngine *> EngineMap;
00039 
00040     inline const QwtTextEngine *engine( EngineMap::const_iterator &it ) const
00041     {
00042         return it.value();
00043     }
00044 
00045     EngineMap d_map;
00046 };
00047 
00048 QwtTextEngineDict &QwtTextEngineDict::dict()
00049 {
00050     static QwtTextEngineDict engineDict;
00051     return engineDict;
00052 }
00053 
00054 QwtTextEngineDict::QwtTextEngineDict()
00055 {
00056     d_map.insert( QwtText::PlainText, new QwtPlainTextEngine() );
00057 #ifndef QT_NO_RICHTEXT
00058     d_map.insert( QwtText::RichText, new QwtRichTextEngine() );
00059 #endif
00060 }
00061 
00062 QwtTextEngineDict::~QwtTextEngineDict()
00063 {
00064     for ( EngineMap::const_iterator it = d_map.begin();
00065         it != d_map.end(); ++it )
00066     {
00067         const QwtTextEngine *textEngine = engine( it );
00068         delete textEngine;
00069     }
00070 }
00071 
00072 const QwtTextEngine *QwtTextEngineDict::textEngine( const QString& text,
00073     QwtText::TextFormat format ) const
00074 {
00075     if ( format == QwtText::AutoText )
00076     {
00077         for ( EngineMap::const_iterator it = d_map.begin();
00078             it != d_map.end(); ++it )
00079         {
00080             if ( it.key() != QwtText::PlainText )
00081             {
00082                 const QwtTextEngine *e = engine( it );
00083                 if ( e && e->mightRender( text ) )
00084                     return e;
00085             }
00086         }
00087     }
00088 
00089     EngineMap::const_iterator it = d_map.find( format );
00090     if ( it != d_map.end() )
00091     {
00092         const QwtTextEngine *e = engine( it );
00093         if ( e )
00094             return e;
00095     }
00096 
00097     it = d_map.find( QwtText::PlainText );
00098     return engine( it );
00099 }
00100 
00101 void QwtTextEngineDict::setTextEngine( QwtText::TextFormat format,
00102     QwtTextEngine *engine )
00103 {
00104     if ( format == QwtText::AutoText )
00105         return;
00106 
00107     if ( format == QwtText::PlainText && engine == NULL )
00108         return;
00109 
00110     EngineMap::const_iterator it = d_map.find( format );
00111     if ( it != d_map.end() )
00112     {
00113         const QwtTextEngine *e = this->engine( it );
00114         if ( e )
00115             delete e;
00116 
00117         d_map.remove( format );
00118     }
00119 
00120     if ( engine != NULL )
00121         d_map.insert( format, engine );
00122 }
00123 
00124 const QwtTextEngine *QwtTextEngineDict::textEngine(
00125     QwtText::TextFormat format ) const
00126 {
00127     const QwtTextEngine *e = NULL;
00128 
00129     EngineMap::const_iterator it = d_map.find( format );
00130     if ( it != d_map.end() )
00131         e = engine( it );
00132 
00133     return e;
00134 }
00135 
00136 class QwtText::PrivateData
00137 {
00138 public:
00139     PrivateData():
00140         renderFlags( Qt::AlignCenter ),
00141         borderRadius( 0 ),
00142         borderPen( Qt::NoPen ),
00143         backgroundBrush( Qt::NoBrush ),
00144         paintAttributes( 0 ),
00145         layoutAttributes( 0 ),
00146         textEngine( NULL )
00147     {
00148     }
00149 
00150     int renderFlags;
00151     QString text;
00152     QFont font;
00153     QColor color;
00154     double borderRadius;
00155     QPen borderPen;
00156     QBrush backgroundBrush;
00157 
00158     QwtText::PaintAttributes paintAttributes;
00159     QwtText::LayoutAttributes layoutAttributes;
00160 
00161     const QwtTextEngine *textEngine;
00162 };
00163 
00164 class QwtText::LayoutCache
00165 {
00166 public:
00167     void invalidate()
00168     {
00169         textSize = QSizeF();
00170     }
00171 
00172     QFont font;
00173     QSizeF textSize;
00174 };
00175 
00182 QwtText::QwtText( const QString &text, QwtText::TextFormat textFormat )
00183 {
00184     d_data = new PrivateData;
00185     d_data->text = text;
00186     d_data->textEngine = textEngine( text, textFormat );
00187 
00188     d_layoutCache = new LayoutCache;
00189 }
00190 
00192 QwtText::QwtText( const QwtText &other )
00193 {
00194     d_data = new PrivateData;
00195     *d_data = *other.d_data;
00196 
00197     d_layoutCache = new LayoutCache;
00198     *d_layoutCache = *other.d_layoutCache;
00199 }
00200 
00202 QwtText::~QwtText()
00203 {
00204     delete d_data;
00205     delete d_layoutCache;
00206 }
00207 
00209 QwtText &QwtText::operator=( const QwtText & other )
00210 {
00211     *d_data = *other.d_data;
00212     *d_layoutCache = *other.d_layoutCache;
00213     return *this;
00214 }
00215 
00217 bool QwtText::operator==( const QwtText &other ) const
00218 {
00219     return d_data->renderFlags == other.d_data->renderFlags &&
00220         d_data->text == other.d_data->text &&
00221         d_data->font == other.d_data->font &&
00222         d_data->color == other.d_data->color &&
00223         d_data->borderRadius == other.d_data->borderRadius &&
00224         d_data->borderPen == other.d_data->borderPen &&
00225         d_data->backgroundBrush == other.d_data->backgroundBrush &&
00226         d_data->paintAttributes == other.d_data->paintAttributes &&
00227         d_data->textEngine == other.d_data->textEngine;
00228 }
00229 
00231 bool QwtText::operator!=( const QwtText &other ) const // invalidate
00232 {
00233     return !( other == *this );
00234 }
00235 
00244 void QwtText::setText( const QString &text,
00245     QwtText::TextFormat textFormat )
00246 {
00247     d_data->text = text;
00248     d_data->textEngine = textEngine( text, textFormat );
00249     d_layoutCache->invalidate();
00250 }
00251 
00256 QString QwtText::text() const
00257 {
00258     return d_data->text;
00259 }
00260 
00271 void QwtText::setRenderFlags( int renderFlags )
00272 {
00273     if ( renderFlags != d_data->renderFlags )
00274     {
00275         d_data->renderFlags = renderFlags;
00276         d_layoutCache->invalidate();
00277     }
00278 }
00279 
00284 int QwtText::renderFlags() const
00285 {
00286     return d_data->renderFlags;
00287 }
00288 
00296 void QwtText::setFont( const QFont &font )
00297 {
00298     d_data->font = font;
00299     setPaintAttribute( PaintUsingTextFont );
00300 }
00301 
00303 QFont QwtText::font() const
00304 {
00305     return d_data->font;
00306 }
00307 
00317 QFont QwtText::usedFont( const QFont &defaultFont ) const
00318 {
00319     if ( d_data->paintAttributes & PaintUsingTextFont )
00320         return d_data->font;
00321 
00322     return defaultFont;
00323 }
00324 
00332 void QwtText::setColor( const QColor &color )
00333 {
00334     d_data->color = color;
00335     setPaintAttribute( PaintUsingTextColor );
00336 }
00337 
00339 QColor QwtText::color() const
00340 {
00341     return d_data->color;
00342 }
00343 
00353 QColor QwtText::usedColor( const QColor &defaultColor ) const
00354 {
00355     if ( d_data->paintAttributes & PaintUsingTextColor )
00356         return d_data->color;
00357 
00358     return defaultColor;
00359 }
00360 
00367 void QwtText::setBorderRadius( double radius )
00368 {
00369     d_data->borderRadius = qMax( 0.0, radius );
00370 }
00371 
00376 double QwtText::borderRadius() const
00377 {
00378     return d_data->borderRadius;
00379 }
00380 
00387 void QwtText::setBorderPen( const QPen &pen )
00388 {
00389     d_data->borderPen = pen;
00390     setPaintAttribute( PaintBackground );
00391 }
00392 
00397 QPen QwtText::borderPen() const
00398 {
00399     return d_data->borderPen;
00400 }
00401 
00408 void QwtText::setBackgroundBrush( const QBrush &brush )
00409 {
00410     d_data->backgroundBrush = brush;
00411     setPaintAttribute( PaintBackground );
00412 }
00413 
00418 QBrush QwtText::backgroundBrush() const
00419 {
00420     return d_data->backgroundBrush;
00421 }
00422 
00433 void QwtText::setPaintAttribute( PaintAttribute attribute, bool on )
00434 {
00435     if ( on )
00436         d_data->paintAttributes |= attribute;
00437     else
00438         d_data->paintAttributes &= ~attribute;
00439 }
00440 
00449 bool QwtText::testPaintAttribute( PaintAttribute attribute ) const
00450 {
00451     return d_data->paintAttributes & attribute;
00452 }
00453 
00461 void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on )
00462 {
00463     if ( on )
00464         d_data->layoutAttributes |= attribute;
00465     else
00466         d_data->layoutAttributes &= ~attribute;
00467 }
00468 
00477 bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const
00478 {
00479     return d_data->layoutAttributes | attribute;
00480 }
00481 
00490 double QwtText::heightForWidth( double width, const QFont &defaultFont ) const
00491 {
00492     // We want to calculate in screen metrics. So
00493     // we need a font that uses screen metrics
00494 
00495     const QFont font( usedFont( defaultFont ), QApplication::desktop() );
00496 
00497     double h = 0;
00498 
00499     if ( d_data->layoutAttributes & MinimumLayout )
00500     {
00501         double left, right, top, bottom;
00502         d_data->textEngine->textMargins( font, d_data->text,
00503             left, right, top, bottom );
00504 
00505         h = d_data->textEngine->heightForWidth(
00506             font, d_data->renderFlags, d_data->text,
00507             width + left + right );
00508 
00509         h -= top + bottom;
00510     }
00511     else
00512     {
00513         h = d_data->textEngine->heightForWidth(
00514             font, d_data->renderFlags, d_data->text, width );
00515     }
00516 
00517     return h;
00518 }
00519 
00526 QSizeF QwtText::textSize( const QFont &defaultFont ) const
00527 {
00528     // We want to calculate in screen metrics. So
00529     // we need a font that uses screen metrics
00530 
00531     const QFont font( usedFont( defaultFont ), QApplication::desktop() );
00532 
00533     if ( !d_layoutCache->textSize.isValid()
00534         || d_layoutCache->font != font )
00535     {
00536         d_layoutCache->textSize = d_data->textEngine->textSize(
00537             font, d_data->renderFlags, d_data->text );
00538         d_layoutCache->font = font;
00539     }
00540 
00541     QSizeF sz = d_layoutCache->textSize;
00542 
00543     if ( d_data->layoutAttributes & MinimumLayout )
00544     {
00545         double left, right, top, bottom;
00546         d_data->textEngine->textMargins( font, d_data->text,
00547             left, right, top, bottom );
00548         sz -= QSizeF( left + right, top + bottom );
00549     }
00550 
00551     return sz;
00552 }
00553 
00560 void QwtText::draw( QPainter *painter, const QRectF &rect ) const
00561 {
00562     if ( d_data->paintAttributes & PaintBackground )
00563     {
00564         if ( d_data->borderPen != Qt::NoPen ||
00565             d_data->backgroundBrush != Qt::NoBrush )
00566         {
00567             painter->save();
00568 
00569             painter->setPen( d_data->borderPen );
00570             painter->setBrush( d_data->backgroundBrush );
00571 
00572             if ( d_data->borderRadius == 0 )
00573             {
00574                 QwtPainter::drawRect( painter, rect );
00575             }
00576             else
00577             {
00578                 painter->setRenderHint( QPainter::Antialiasing, true );
00579                 painter->drawRoundedRect( rect,
00580                     d_data->borderRadius, d_data->borderRadius );
00581             }
00582 
00583             painter->restore();
00584         }
00585     }
00586 
00587     painter->save();
00588 
00589     if ( d_data->paintAttributes & PaintUsingTextFont )
00590     {
00591         painter->setFont( d_data->font );
00592     }
00593 
00594     if ( d_data->paintAttributes & PaintUsingTextColor )
00595     {
00596         if ( d_data->color.isValid() )
00597             painter->setPen( d_data->color );
00598     }
00599 
00600     QRectF expandedRect = rect;
00601     if ( d_data->layoutAttributes & MinimumLayout )
00602     {
00603         // We want to calculate in screen metrics. So
00604         // we need a font that uses screen metrics
00605 
00606         const QFont font( painter->font(), QApplication::desktop() );
00607 
00608         double left, right, top, bottom;
00609         d_data->textEngine->textMargins(
00610             font, d_data->text, left, right, top, bottom );
00611 
00612         expandedRect.setTop( rect.top() - top );
00613         expandedRect.setBottom( rect.bottom() + bottom );
00614         expandedRect.setLeft( rect.left() - left );
00615         expandedRect.setRight( rect.right() + right );
00616     }
00617 
00618     d_data->textEngine->draw( painter, expandedRect,
00619         d_data->renderFlags, d_data->text );
00620 
00621     painter->restore();
00622 }
00623 
00639 const QwtTextEngine *QwtText::textEngine( const QString &text,
00640     QwtText::TextFormat format )
00641 {
00642     return QwtTextEngineDict::dict().textEngine( text, format );
00643 }
00644 
00659 void QwtText::setTextEngine( QwtText::TextFormat format,
00660     QwtTextEngine *engine )
00661 {
00662     QwtTextEngineDict::dict().setTextEngine( format, engine );
00663 }
00664 
00673 const QwtTextEngine *QwtText::textEngine( QwtText::TextFormat format )
00674 {
00675     return  QwtTextEngineDict::dict().textEngine( format );
00676 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:57