123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 |
- /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
- * Qwt Widget Library
- * Copyright (C) 1997 Josef Wilgen
- * Copyright (C) 2003 Uwe Rathmann
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the Qwt License, Version 1.0
- *****************************************************************************/
- #include "qwt_text.h"
- #include "qwt_painter.h"
- #include "qwt_text_engine.h"
- #include <qmap.h>
- #include <qfont.h>
- #include <qcolor.h>
- #include <qpen.h>
- #include <qbrush.h>
- #include <qpainter.h>
- #include <qapplication.h>
- #include <qdesktopwidget.h>
- #include <qmath.h>
- class QwtTextEngineDict
- {
- public:
- static QwtTextEngineDict &dict();
- void setTextEngine( QwtText::TextFormat, QwtTextEngine * );
- const QwtTextEngine *textEngine( QwtText::TextFormat ) const;
- const QwtTextEngine *textEngine( const QString &,
- QwtText::TextFormat ) const;
- private:
- QwtTextEngineDict();
- ~QwtTextEngineDict();
- typedef QMap<int, QwtTextEngine *> EngineMap;
- inline const QwtTextEngine *engine( EngineMap::const_iterator &it ) const
- {
- return it.value();
- }
- EngineMap d_map;
- };
- QwtTextEngineDict &QwtTextEngineDict::dict()
- {
- static QwtTextEngineDict engineDict;
- return engineDict;
- }
- QwtTextEngineDict::QwtTextEngineDict()
- {
- d_map.insert( QwtText::PlainText, new QwtPlainTextEngine() );
- #ifndef QT_NO_RICHTEXT
- d_map.insert( QwtText::RichText, new QwtRichTextEngine() );
- #endif
- }
- QwtTextEngineDict::~QwtTextEngineDict()
- {
- for ( EngineMap::const_iterator it = d_map.begin();
- it != d_map.end(); ++it )
- {
- const QwtTextEngine *textEngine = engine( it );
- delete textEngine;
- }
- }
- const QwtTextEngine *QwtTextEngineDict::textEngine( const QString& text,
- QwtText::TextFormat format ) const
- {
- if ( format == QwtText::AutoText )
- {
- for ( EngineMap::const_iterator it = d_map.begin();
- it != d_map.end(); ++it )
- {
- if ( it.key() != QwtText::PlainText )
- {
- const QwtTextEngine *e = engine( it );
- if ( e && e->mightRender( text ) )
- return e;
- }
- }
- }
- EngineMap::const_iterator it = d_map.find( format );
- if ( it != d_map.end() )
- {
- const QwtTextEngine *e = engine( it );
- if ( e )
- return e;
- }
- it = d_map.find( QwtText::PlainText );
- return engine( it );
- }
- void QwtTextEngineDict::setTextEngine( QwtText::TextFormat format,
- QwtTextEngine *engine )
- {
- if ( format == QwtText::AutoText )
- return;
- if ( format == QwtText::PlainText && engine == NULL )
- return;
- EngineMap::const_iterator it = d_map.find( format );
- if ( it != d_map.end() )
- {
- const QwtTextEngine *e = this->engine( it );
- if ( e )
- delete e;
- d_map.remove( format );
- }
- if ( engine != NULL )
- d_map.insert( format, engine );
- }
- const QwtTextEngine *QwtTextEngineDict::textEngine(
- QwtText::TextFormat format ) const
- {
- const QwtTextEngine *e = NULL;
- EngineMap::const_iterator it = d_map.find( format );
- if ( it != d_map.end() )
- e = engine( it );
- return e;
- }
- class QwtText::PrivateData
- {
- public:
- PrivateData():
- renderFlags( Qt::AlignCenter ),
- backgroundPen( Qt::NoPen ),
- backgroundBrush( Qt::NoBrush ),
- paintAttributes( 0 ),
- layoutAttributes( 0 ),
- textEngine( NULL )
- {
- }
- int renderFlags;
- QString text;
- QFont font;
- QColor color;
- QPen backgroundPen;
- QBrush backgroundBrush;
- int paintAttributes;
- int layoutAttributes;
- const QwtTextEngine *textEngine;
- };
- class QwtText::LayoutCache
- {
- public:
- void invalidate()
- {
- textSize = QSizeF();
- }
- QFont font;
- QSizeF textSize;
- };
- /*!
- Constructor
- \param text Text content
- \param textFormat Text format
- */
- QwtText::QwtText( const QString &text, QwtText::TextFormat textFormat )
- {
- d_data = new PrivateData;
- d_data->text = text;
- d_data->textEngine = textEngine( text, textFormat );
- d_layoutCache = new LayoutCache;
- }
- //! Copy constructor
- QwtText::QwtText( const QwtText &other )
- {
- d_data = new PrivateData;
- *d_data = *other.d_data;
- d_layoutCache = new LayoutCache;
- *d_layoutCache = *other.d_layoutCache;
- }
- //! Destructor
- QwtText::~QwtText()
- {
- delete d_data;
- delete d_layoutCache;
- }
- //! Assignment operator
- QwtText &QwtText::operator=( const QwtText & other )
- {
- *d_data = *other.d_data;
- *d_layoutCache = *other.d_layoutCache;
- return *this;
- }
- //! Relational operator
- bool QwtText::operator==( const QwtText &other ) const
- {
- return d_data->renderFlags == other.d_data->renderFlags &&
- d_data->text == other.d_data->text &&
- d_data->font == other.d_data->font &&
- d_data->color == other.d_data->color &&
- d_data->backgroundPen == other.d_data->backgroundPen &&
- d_data->backgroundBrush == other.d_data->backgroundBrush &&
- d_data->paintAttributes == other.d_data->paintAttributes &&
- d_data->textEngine == other.d_data->textEngine;
- }
- //! Relational operator
- bool QwtText::operator!=( const QwtText &other ) const // invalidate
- {
- return !( other == *this );
- }
- /*!
- Assign a new text content
- \param text Text content
- \param textFormat Text format
- \sa text()
- */
- void QwtText::setText( const QString &text,
- QwtText::TextFormat textFormat )
- {
- d_data->text = text;
- d_data->textEngine = textEngine( text, textFormat );
- d_layoutCache->invalidate();
- }
- /*!
- Return the text.
- \sa setText()
- */
- QString QwtText::text() const
- {
- return d_data->text;
- }
- /*!
- \brief Change the render flags
- The default setting is Qt::AlignCenter
- \param renderFlags Bitwise OR of the flags used like in QPainter::drawText
- \sa renderFlags(), QwtTextEngine::draw()
- \note Some renderFlags might have no effect, depending on the text format.
- */
- void QwtText::setRenderFlags( int renderFlags )
- {
- if ( renderFlags != d_data->renderFlags )
- {
- d_data->renderFlags = renderFlags;
- d_layoutCache->invalidate();
- }
- }
- /*!
- \return Render flags
- \sa setRenderFlags()
- */
- int QwtText::renderFlags() const
- {
- return d_data->renderFlags;
- }
- /*!
- Set the font.
- \param font Font
- \note Setting the font might have no effect, when
- the text contains control sequences for setting fonts.
- */
- void QwtText::setFont( const QFont &font )
- {
- d_data->font = font;
- setPaintAttribute( PaintUsingTextFont );
- }
- //! Return the font.
- QFont QwtText::font() const
- {
- return d_data->font;
- }
- /*!
- Return the font of the text, if it has one.
- Otherwise return defaultFont.
- \param defaultFont Default font
- \sa setFont(), font(), PaintAttributes
- */
- QFont QwtText::usedFont( const QFont &defaultFont ) const
- {
- if ( d_data->paintAttributes & PaintUsingTextFont )
- return d_data->font;
- return defaultFont;
- }
- /*!
- Set the pen color used for painting the text.
- \param color Color
- \note Setting the color might have no effect, when
- the text contains control sequences for setting colors.
- */
- void QwtText::setColor( const QColor &color )
- {
- d_data->color = color;
- setPaintAttribute( PaintUsingTextColor );
- }
- //! Return the pen color, used for painting the text
- QColor QwtText::color() const
- {
- return d_data->color;
- }
- /*!
- Return the color of the text, if it has one.
- Otherwise return defaultColor.
- \param defaultColor Default color
- \sa setColor(), color(), PaintAttributes
- */
- QColor QwtText::usedColor( const QColor &defaultColor ) const
- {
- if ( d_data->paintAttributes & PaintUsingTextColor )
- return d_data->color;
- return defaultColor;
- }
- /*!
- Set the background pen
- \param pen Background pen
- \sa backgroundPen(), setBackgroundBrush()
- */
- void QwtText::setBackgroundPen( const QPen &pen )
- {
- d_data->backgroundPen = pen;
- setPaintAttribute( PaintBackground );
- }
- /*!
- \return Background pen
- \sa setBackgroundPen(), backgroundBrush()
- */
- QPen QwtText::backgroundPen() const
- {
- return d_data->backgroundPen;
- }
- /*!
- Set the background brush
- \param brush Background brush
- \sa backgroundBrush(), setBackgroundPen()
- */
- void QwtText::setBackgroundBrush( const QBrush &brush )
- {
- d_data->backgroundBrush = brush;
- setPaintAttribute( PaintBackground );
- }
- /*!
- \return Background brush
- \sa setBackgroundBrush(), backgroundPen()
- */
- QBrush QwtText::backgroundBrush() const
- {
- return d_data->backgroundBrush;
- }
- /*!
- Change a paint attribute
- \param attribute Paint attribute
- \param on On/Off
- \note Used by setFont(), setColor(),
- setBackgroundPen() and setBackgroundBrush()
- \sa testPaintAttribute()
- */
- void QwtText::setPaintAttribute( PaintAttribute attribute, bool on )
- {
- if ( on )
- d_data->paintAttributes |= attribute;
- else
- d_data->paintAttributes &= ~attribute;
- }
- /*!
- Test a paint attribute
- \param attribute Paint attribute
- \return true, if attribute is enabled
- \sa setPaintAttribute()
- */
- bool QwtText::testPaintAttribute( PaintAttribute attribute ) const
- {
- return d_data->paintAttributes & attribute;
- }
- /*!
- Change a layout attribute
- \param attribute Layout attribute
- \param on On/Off
- \sa testLayoutAttribute()
- */
- void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on )
- {
- if ( on )
- d_data->layoutAttributes |= attribute;
- else
- d_data->layoutAttributes &= ~attribute;
- }
- /*!
- Test a layout attribute
- \param attribute Layout attribute
- \return true, if attribute is enabled
- \sa setLayoutAttribute()
- */
- bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const
- {
- return d_data->layoutAttributes | attribute;
- }
- /*!
- Find the height for a given width
- \param defaultFont Font, used for the calculation if the text has no font
- \param width Width
- \return Calculated height
- */
- double QwtText::heightForWidth( double width, const QFont &defaultFont ) const
- {
- // We want to calculate in screen metrics. So
- // we need a font that uses screen metrics
- const QFont font( usedFont( defaultFont ), QApplication::desktop() );
- double h = 0;
- if ( d_data->layoutAttributes & MinimumLayout )
- {
- double left, right, top, bottom;
- d_data->textEngine->textMargins( font, d_data->text,
- left, right, top, bottom );
- h = d_data->textEngine->heightForWidth(
- font, d_data->renderFlags, d_data->text,
- width + left + right );
- h -= top + bottom;
- }
- else
- {
- h = d_data->textEngine->heightForWidth(
- font, d_data->renderFlags, d_data->text, width );
- }
- return h;
- }
- /*!
- Find the height for a given width
- \param defaultFont Font, used for the calculation if the text has no font
- \return Calculated height
- */
- /*!
- Returns the size, that is needed to render text
- \param defaultFont Font of the text
- \return Caluclated size
- */
- QSizeF QwtText::textSize( const QFont &defaultFont ) const
- {
- // We want to calculate in screen metrics. So
- // we need a font that uses screen metrics
- const QFont font( usedFont( defaultFont ), QApplication::desktop() );
- if ( !d_layoutCache->textSize.isValid()
- || d_layoutCache->font != font )
- {
- d_layoutCache->textSize = d_data->textEngine->textSize(
- font, d_data->renderFlags, d_data->text );
- d_layoutCache->font = font;
- }
- QSizeF sz = d_layoutCache->textSize;
- if ( d_data->layoutAttributes & MinimumLayout )
- {
- double left, right, top, bottom;
- d_data->textEngine->textMargins( font, d_data->text,
- left, right, top, bottom );
- sz -= QSizeF( left + right, top + bottom );
- }
- return sz;
- }
- /*!
- Draw a text into a rectangle
- \param painter Painter
- \param rect Rectangle
- */
- void QwtText::draw( QPainter *painter, const QRectF &rect ) const
- {
- if ( d_data->paintAttributes & PaintBackground )
- {
- if ( d_data->backgroundPen != Qt::NoPen ||
- d_data->backgroundBrush != Qt::NoBrush )
- {
- painter->save();
- painter->setPen( d_data->backgroundPen );
- painter->setBrush( d_data->backgroundBrush );
- QwtPainter::drawRect( painter, rect );
- painter->restore();
- }
- }
- painter->save();
- if ( d_data->paintAttributes & PaintUsingTextFont )
- {
- painter->setFont( d_data->font );
- }
- if ( d_data->paintAttributes & PaintUsingTextColor )
- {
- if ( d_data->color.isValid() )
- painter->setPen( d_data->color );
- }
- QRectF expandedRect = rect;
- if ( d_data->layoutAttributes & MinimumLayout )
- {
- // We want to calculate in screen metrics. So
- // we need a font that uses screen metrics
- const QFont font( painter->font(), QApplication::desktop() );
- double left, right, top, bottom;
- d_data->textEngine->textMargins(
- font, d_data->text, left, right, top, bottom );
- expandedRect.setTop( rect.top() - top );
- expandedRect.setBottom( rect.bottom() + bottom );
- expandedRect.setLeft( rect.left() - left );
- expandedRect.setRight( rect.right() + right );
- }
- d_data->textEngine->draw( painter, expandedRect,
- d_data->renderFlags, d_data->text );
- painter->restore();
- }
- /*!
- Find the text engine for a text format
- In case of QwtText::AutoText the first text engine
- (beside QwtPlainTextEngine) is returned, where QwtTextEngine::mightRender
- returns true. If there is none QwtPlainTextEngine is returnd.
- If no text engine is registered for the format QwtPlainTextEngine
- is returnd.
- \param text Text, needed in case of AutoText
- \param format Text format
- */
- const QwtTextEngine *QwtText::textEngine( const QString &text,
- QwtText::TextFormat format )
- {
- return QwtTextEngineDict::dict().textEngine( text, format );
- }
- /*!
- Assign/Replace a text engine for a text format
- With setTextEngine it is possible to extend Qwt with
- other types of text formats.
- For QwtText::PlainText it is not allowed to assign a engine == NULL.
- \param format Text format
- \param engine Text engine
- \sa QwtMathMLTextEngine
- \warning Using QwtText::AutoText does nothing.
- */
- void QwtText::setTextEngine( QwtText::TextFormat format,
- QwtTextEngine *engine )
- {
- QwtTextEngineDict::dict().setTextEngine( format, engine );
- }
- /*!
- \brief Find the text engine for a text format
- textEngine can be used to find out if a text format is supported.
- \param format Text format
- \return The text engine, or NULL if no engine is available.
- */
- const QwtTextEngine *QwtText::textEngine( QwtText::TextFormat format )
- {
- return QwtTextEngineDict::dict().textEngine( format );
- }
|