qwt_text.cpp
/******************************************************************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 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 "qwt_math.h"
#include <qmap.h>
#include <qfont.h>
#include <qcolor.h>
#include <qpen.h>
#include <qbrush.h>
#include <qpainter.h>
#if QT_VERSION >= 0x050200
static QwtText qwtStringToText( const QString& text )
{
return QwtText( text );
}
#endif
namespace
{
static const struct RegisterQwtText
{
inline RegisterQwtText()
{
qRegisterMetaType< QwtText >();
#if QT_VERSION >= 0x050200
QMetaType::registerConverter< QString, QwtText >( qwtStringToText );
#endif
}
} qwtRegisterQwtText;
}
namespace
{
class TextEngineDict
{
public:
static TextEngineDict& dict();
void setTextEngine( QwtText::TextFormat, QwtTextEngine* );
const QwtTextEngine* textEngine( QwtText::TextFormat ) const;
const QwtTextEngine* textEngine( const QString&,
QwtText::TextFormat ) const;
private:
TextEngineDict();
~TextEngineDict();
typedef QMap< int, QwtTextEngine* > EngineMap;
inline const QwtTextEngine* engine( EngineMap::const_iterator& it ) const
{
return it.value();
}
EngineMap m_map;
};
TextEngineDict& TextEngineDict::dict()
{
static TextEngineDict engineDict;
return engineDict;
}
TextEngineDict::TextEngineDict()
{
m_map.insert( QwtText::PlainText, new QwtPlainTextEngine() );
#ifndef QT_NO_RICHTEXT
m_map.insert( QwtText::RichText, new QwtRichTextEngine() );
#endif
}
TextEngineDict::~TextEngineDict()
{
for ( EngineMap::const_iterator it = m_map.constBegin();
it != m_map.constEnd(); ++it )
{
const QwtTextEngine* textEngine = engine( it );
delete textEngine;
}
}
const QwtTextEngine* TextEngineDict::textEngine( const QString& text,
QwtText::TextFormat format ) const
{
if ( format == QwtText::AutoText )
{
for ( EngineMap::const_iterator it = m_map.begin();
it != m_map.end(); ++it )
{
if ( it.key() != QwtText::PlainText )
{
const QwtTextEngine* e = engine( it );
if ( e && e->mightRender( text ) )
return e;
}
}
}
EngineMap::const_iterator it = m_map.find( format );
if ( it != m_map.end() )
{
const QwtTextEngine* e = engine( it );
if ( e )
return e;
}
it = m_map.find( QwtText::PlainText );
return engine( it );
}
void TextEngineDict::setTextEngine( QwtText::TextFormat format,
QwtTextEngine* engine )
{
if ( format == QwtText::AutoText )
return;
if ( format == QwtText::PlainText && engine == NULL )
return;
EngineMap::const_iterator it = m_map.constFind( format );
if ( it != m_map.constEnd() )
{
delete this->engine( it );
m_map.remove( format );
}
if ( engine != NULL )
m_map.insert( format, engine );
}
const QwtTextEngine* TextEngineDict::textEngine(
QwtText::TextFormat format ) const
{
const QwtTextEngine* e = NULL;
EngineMap::const_iterator it = m_map.find( format );
if ( it != m_map.end() )
e = engine( it );
return e;
}
}
class QwtText::PrivateData
{
public:
PrivateData():
renderFlags( Qt::AlignCenter ),
borderRadius( 0 ),
borderPen( Qt::NoPen ),
backgroundBrush( Qt::NoBrush ),
textEngine( NULL )
{
}
int renderFlags;
QString text;
QFont font;
QColor color;
double borderRadius;
QPen borderPen;
QBrush backgroundBrush;
QwtText::PaintAttributes paintAttributes;
QwtText::LayoutAttributes layoutAttributes;
const QwtTextEngine* textEngine;
};
class QwtText::LayoutCache
{
public:
void invalidate()
{
textSize = QSizeF();
}
QFont font;
QSizeF textSize;
};
QwtText::QwtText()
{
m_data = new PrivateData;
m_data->textEngine = textEngine( m_data->text, PlainText );
m_layoutCache = new LayoutCache;
}
QwtText::QwtText( const QString& text, QwtText::TextFormat textFormat )
{
m_data = new PrivateData;
m_data->text = text;
m_data->textEngine = textEngine( text, textFormat );
m_layoutCache = new LayoutCache;
}
QwtText::QwtText( const QwtText& other )
{
m_data = new PrivateData;
*m_data = *other.m_data;
m_layoutCache = new LayoutCache;
*m_layoutCache = *other.m_layoutCache;
}
QwtText::~QwtText()
{
delete m_data;
delete m_layoutCache;
}
QwtText& QwtText::operator=( const QwtText& other )
{
*m_data = *other.m_data;
*m_layoutCache = *other.m_layoutCache;
return *this;
}
bool QwtText::operator==( const QwtText& other ) const
{
return m_data->renderFlags == other.m_data->renderFlags &&
m_data->text == other.m_data->text &&
m_data->font == other.m_data->font &&
m_data->color == other.m_data->color &&
m_data->borderRadius == other.m_data->borderRadius &&
m_data->borderPen == other.m_data->borderPen &&
m_data->backgroundBrush == other.m_data->backgroundBrush &&
m_data->paintAttributes == other.m_data->paintAttributes &&
m_data->textEngine == other.m_data->textEngine;
}
bool QwtText::operator!=( const QwtText& other ) const // invalidate
{
return !( other == *this );
}
void QwtText::setText( const QString& text,
QwtText::TextFormat textFormat )
{
m_data->text = text;
m_data->textEngine = textEngine( text, textFormat );
m_layoutCache->invalidate();
}
QString QwtText::text() const
{
return m_data->text;
}
void QwtText::setRenderFlags( int renderFlags )
{
if ( renderFlags != m_data->renderFlags )
{
m_data->renderFlags = renderFlags;
m_layoutCache->invalidate();
}
}
int QwtText::renderFlags() const
{
return m_data->renderFlags;
}
void QwtText::setFont( const QFont& font )
{
m_data->font = font;
setPaintAttribute( PaintUsingTextFont );
}
QFont QwtText::font() const
{
return m_data->font;
}
QFont QwtText::usedFont( const QFont& defaultFont ) const
{
if ( m_data->paintAttributes & PaintUsingTextFont )
return m_data->font;
return defaultFont;
}
void QwtText::setColor( const QColor& color )
{
m_data->color = color;
setPaintAttribute( PaintUsingTextColor );
}
QColor QwtText::color() const
{
return m_data->color;
}
QColor QwtText::usedColor( const QColor& defaultColor ) const
{
if ( m_data->paintAttributes & PaintUsingTextColor )
return m_data->color;
return defaultColor;
}
void QwtText::setBorderRadius( double radius )
{
m_data->borderRadius = qwtMaxF( 0.0, radius );
}
double QwtText::borderRadius() const
{
return m_data->borderRadius;
}
void QwtText::setBorderPen( const QPen& pen )
{
m_data->borderPen = pen;
setPaintAttribute( PaintBackground );
}
QPen QwtText::borderPen() const
{
return m_data->borderPen;
}
void QwtText::setBackgroundBrush( const QBrush& brush )
{
m_data->backgroundBrush = brush;
setPaintAttribute( PaintBackground );
}
QBrush QwtText::backgroundBrush() const
{
return m_data->backgroundBrush;
}
void QwtText::setPaintAttribute( PaintAttribute attribute, bool on )
{
if ( on )
m_data->paintAttributes |= attribute;
else
m_data->paintAttributes &= ~attribute;
}
bool QwtText::testPaintAttribute( PaintAttribute attribute ) const
{
return m_data->paintAttributes & attribute;
}
void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on )
{
if ( on )
m_data->layoutAttributes |= attribute;
else
m_data->layoutAttributes &= ~attribute;
}
bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const
{
return m_data->layoutAttributes | attribute;
}
double QwtText::heightForWidth( double width ) const
{
return heightForWidth( width, QFont() );
}
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 = QwtPainter::scaledFont( usedFont( defaultFont ) );
double h = 0;
if ( m_data->layoutAttributes & MinimumLayout )
{
double left, right, top, bottom;
m_data->textEngine->textMargins( font, m_data->text,
left, right, top, bottom );
h = m_data->textEngine->heightForWidth(
font, m_data->renderFlags, m_data->text,
width + left + right );
h -= top + bottom;
}
else
{
h = m_data->textEngine->heightForWidth(
font, m_data->renderFlags, m_data->text, width );
}
return h;
}
QSizeF QwtText::textSize() const
{
return textSize( QFont() );
}
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 = QwtPainter::scaledFont( usedFont( defaultFont ) );
if ( !m_layoutCache->textSize.isValid()
|| m_layoutCache->font != font )
{
m_layoutCache->textSize = m_data->textEngine->textSize(
font, m_data->renderFlags, m_data->text );
m_layoutCache->font = font;
}
QSizeF sz = m_layoutCache->textSize;
if ( m_data->layoutAttributes & MinimumLayout )
{
double left, right, top, bottom;
m_data->textEngine->textMargins( font, m_data->text,
left, right, top, bottom );
sz -= QSizeF( left + right, top + bottom );
}
return sz;
}
void QwtText::draw( QPainter* painter, const QRectF& rect ) const
{
if ( m_data->paintAttributes & PaintBackground )
{
if ( m_data->borderPen != Qt::NoPen ||
m_data->backgroundBrush != Qt::NoBrush )
{
painter->save();
painter->setPen( m_data->borderPen );
painter->setBrush( m_data->backgroundBrush );
if ( m_data->borderRadius == 0 )
{
QwtPainter::drawRect( painter, rect );
}
else
{
painter->setRenderHint( QPainter::Antialiasing, true );
painter->drawRoundedRect( rect,
m_data->borderRadius, m_data->borderRadius );
}
painter->restore();
}
}
painter->save();
if ( m_data->paintAttributes & PaintUsingTextFont )
{
painter->setFont( m_data->font );
}
if ( m_data->paintAttributes & PaintUsingTextColor )
{
if ( m_data->color.isValid() )
painter->setPen( m_data->color );
}
QRectF expandedRect = rect;
if ( m_data->layoutAttributes & MinimumLayout )
{
// We want to calculate in screen metrics. So
// we need a font that uses screen metrics
const QFont font = QwtPainter::scaledFont( painter->font() );
double left, right, top, bottom;
m_data->textEngine->textMargins(
font, m_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 );
}
m_data->textEngine->draw( painter, expandedRect,
m_data->renderFlags, m_data->text );
painter->restore();
}
const QwtTextEngine* QwtText::textEngine( const QString& text,
QwtText::TextFormat format )
{
return TextEngineDict::dict().textEngine( text, format );
}
void QwtText::setTextEngine( QwtText::TextFormat format,
QwtTextEngine* engine )
{
TextEngineDict::dict().setTextEngine( format, engine );
}
const QwtTextEngine* QwtText::textEngine( QwtText::TextFormat format )
{
return TextEngineDict::dict().textEngine( format );
}
bool QwtText::isNull() const
{
return m_data->text.isNull();
}
bool QwtText::isEmpty() const
{
return m_data->text.isEmpty();
}
QMap
Definition: qwt_compass.h:19
QwtPainter::drawRect
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
Definition: qwt_painter.cpp:347
QwtPainter::scaledFont
static QFont scaledFont(const QFont &, const QPaintDevice *=nullptr)
Definition: qwt_painter.cpp:1450
QwtPlainTextEngine
A text engine for plain texts.
Definition: qwt_text_engine.h:112
QwtRichTextEngine
A text engine for Qt rich texts.
Definition: qwt_text_engine.h:148
QwtTextEngine
Abstract base class for rendering text strings.
Definition: qwt_text_engine.h:31
QwtTextEngine::mightRender
virtual bool mightRender(const QString &text) const =0
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtText::textEngine
static const QwtTextEngine * textEngine(const QString &text, QwtText::TextFormat=AutoText)
Definition: qwt_text.cpp:694
QwtText::LayoutAttribute
LayoutAttribute
Layout Attributes The layout attributes affects some aspects of the layout of the text.
Definition: qwt_text.h:133
QwtText::MinimumLayout
@ MinimumLayout
Definition: qwt_text.h:140
QwtText::operator==
bool operator==(const QwtText &) const
Relational operator.
Definition: qwt_text.cpp:250
QwtText::backgroundBrush
QBrush backgroundBrush() const
Definition: qwt_text.cpp:451
QwtText::usedColor
QColor usedColor(const QColor &) const
Definition: qwt_text.cpp:386
QwtText::QwtText
QwtText()
Definition: qwt_text.cpp:201
QwtText::setLayoutAttribute
void setLayoutAttribute(LayoutAttribute, bool on=true)
Definition: qwt_text.cpp:494
QwtText::testPaintAttribute
bool testPaintAttribute(PaintAttribute) const
Definition: qwt_text.cpp:482
QwtText::textSize
QSizeF textSize() const
Definition: qwt_text.cpp:570
QwtText::renderFlags
int renderFlags() const
Definition: qwt_text.cpp:317
QwtText::borderRadius
double borderRadius() const
Definition: qwt_text.cpp:409
QwtText::TextFormat
TextFormat
Text format.
Definition: qwt_text.h:65
QwtText::AutoText
@ AutoText
Definition: qwt_text.h:72
QwtText::RichText
@ RichText
Use the Scribe framework (Qt Rich Text) to render the text.
Definition: qwt_text.h:78
QwtText::PlainText
@ PlainText
Draw the text as it is, using a QwtPlainTextEngine.
Definition: qwt_text.h:75
QwtText::font
QFont font() const
Return the font.
Definition: qwt_text.cpp:336
QwtText::color
QColor color() const
Return the pen color, used for painting the text.
Definition: qwt_text.cpp:372
QwtText::setBorderRadius
void setBorderRadius(double)
Definition: qwt_text.cpp:400
QwtText::LayoutAttributes
QFlags< LayoutAttribute > LayoutAttributes
Definition: qwt_text.h:143
QwtText::PaintAttribute
PaintAttribute
Paint Attributes.
Definition: qwt_text.h:115
QwtText::PaintUsingTextColor
@ PaintUsingTextColor
The text has an individual color.
Definition: qwt_text.h:120
QwtText::PaintBackground
@ PaintBackground
The text has an individual background.
Definition: qwt_text.h:123
QwtText::PaintUsingTextFont
@ PaintUsingTextFont
The text has an individual font.
Definition: qwt_text.h:117
QwtText::setText
void setText(const QString &, QwtText::TextFormat textFormat=AutoText)
Definition: qwt_text.cpp:277
QwtText::isEmpty
bool isEmpty() const
Definition: qwt_text.cpp:739
QwtText::setPaintAttribute
void setPaintAttribute(PaintAttribute, bool on=true)
Definition: qwt_text.cpp:466
QwtText::operator!=
bool operator!=(const QwtText &) const
Relational operator.
Definition: qwt_text.cpp:264
QwtText::~QwtText
~QwtText()
Destructor.
Definition: qwt_text.cpp:235
QwtText::setColor
void setColor(const QColor &)
Definition: qwt_text.cpp:365
QwtText::setBorderPen
void setBorderPen(const QPen &)
Definition: qwt_text.cpp:420
QwtText::setFont
void setFont(const QFont &)
Definition: qwt_text.cpp:329
QwtText::operator=
QwtText & operator=(const QwtText &)
Assignment operator.
Definition: qwt_text.cpp:242
QwtText::testLayoutAttribute
bool testLayoutAttribute(LayoutAttribute) const
Definition: qwt_text.cpp:510
QwtText::draw
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:615
QwtText::text
QString text() const
Definition: qwt_text.cpp:289
QwtText::isNull
bool isNull() const
Definition: qwt_text.cpp:733
QwtText::PaintAttributes
QFlags< PaintAttribute > PaintAttributes
Definition: qwt_text.h:126
QwtText::setTextEngine
static void setTextEngine(QwtText::TextFormat, QwtTextEngine *)
Definition: qwt_text.cpp:713
QwtText::setBackgroundBrush
void setBackgroundBrush(const QBrush &)
Definition: qwt_text.cpp:441
QwtText::borderPen
QPen borderPen() const
Definition: qwt_text.cpp:430
QwtText::heightForWidth
double heightForWidth(double width) const
Definition: qwt_text.cpp:522
QwtText::setRenderFlags
void setRenderFlags(int)
Change the render flags.
Definition: qwt_text.cpp:304
QwtText::usedFont
QFont usedFont(const QFont &) const
Definition: qwt_text.cpp:350