Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_text.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_text.h"
11#include "qwt_painter.h"
12#include "qwt_text_engine.h"
13#include "qwt_math.h"
14
15#include <qmap.h>
16#include <qfont.h>
17#include <qcolor.h>
18#include <qpen.h>
19#include <qbrush.h>
20#include <qpainter.h>
21
22#if QT_VERSION >= 0x050200
23
24static QwtText qwtStringToText( const QString& text )
25{
26 return QwtText( text );
27}
28
29#endif
30
31namespace
32{
33 static const struct RegisterQwtText
34 {
35 inline RegisterQwtText()
36 {
37 qRegisterMetaType< QwtText >();
38
39#if QT_VERSION >= 0x050200
40 QMetaType::registerConverter< QString, QwtText >( qwtStringToText );
41#endif
42 }
43
44 } qwtRegisterQwtText;
45}
46
47namespace
48{
49 class TextEngineDict
50 {
51 public:
52 static TextEngineDict& dict();
53
54 void setTextEngine( QwtText::TextFormat, QwtTextEngine* );
55
56 const QwtTextEngine* textEngine( QwtText::TextFormat ) const;
57 const QwtTextEngine* textEngine( const QString&,
58 QwtText::TextFormat ) const;
59
60 private:
61 TextEngineDict();
62 ~TextEngineDict();
63
64 typedef QMap< int, QwtTextEngine* > EngineMap;
65
66 inline const QwtTextEngine* engine( EngineMap::const_iterator& it ) const
67 {
68 return it.value();
69 }
70
71 EngineMap m_map;
72 };
73
74 TextEngineDict& TextEngineDict::dict()
75 {
76 static TextEngineDict engineDict;
77 return engineDict;
78 }
79
80 TextEngineDict::TextEngineDict()
81 {
82 m_map.insert( QwtText::PlainText, new QwtPlainTextEngine() );
83 #ifndef QT_NO_RICHTEXT
84 m_map.insert( QwtText::RichText, new QwtRichTextEngine() );
85 #endif
86 }
87
88 TextEngineDict::~TextEngineDict()
89 {
90 for ( EngineMap::const_iterator it = m_map.constBegin();
91 it != m_map.constEnd(); ++it )
92 {
93 const QwtTextEngine* textEngine = engine( it );
94 delete textEngine;
95 }
96 }
97
98 const QwtTextEngine* TextEngineDict::textEngine( const QString& text,
99 QwtText::TextFormat format ) const
100 {
101 if ( format == QwtText::AutoText )
102 {
103 for ( EngineMap::const_iterator it = m_map.begin();
104 it != m_map.end(); ++it )
105 {
106 if ( it.key() != QwtText::PlainText )
107 {
108 const QwtTextEngine* e = engine( it );
109 if ( e && e->mightRender( text ) )
110 return e;
111 }
112 }
113 }
114
115 EngineMap::const_iterator it = m_map.find( format );
116 if ( it != m_map.end() )
117 {
118 const QwtTextEngine* e = engine( it );
119 if ( e )
120 return e;
121 }
122
123 it = m_map.find( QwtText::PlainText );
124 return engine( it );
125 }
126
127 void TextEngineDict::setTextEngine( QwtText::TextFormat format,
128 QwtTextEngine* engine )
129 {
130 if ( format == QwtText::AutoText )
131 return;
132
133 if ( format == QwtText::PlainText && engine == NULL )
134 return;
135
136 EngineMap::const_iterator it = m_map.constFind( format );
137 if ( it != m_map.constEnd() )
138 {
139 delete this->engine( it );
140 m_map.remove( format );
141 }
142
143 if ( engine != NULL )
144 m_map.insert( format, engine );
145 }
146
147 const QwtTextEngine* TextEngineDict::textEngine(
148 QwtText::TextFormat format ) const
149 {
150 const QwtTextEngine* e = NULL;
151
152 EngineMap::const_iterator it = m_map.find( format );
153 if ( it != m_map.end() )
154 e = engine( it );
155
156 return e;
157 }
158}
159
160class QwtText::PrivateData
161{
162 public:
163 PrivateData():
164 renderFlags( Qt::AlignCenter ),
165 borderRadius( 0 ),
166 borderPen( Qt::NoPen ),
167 backgroundBrush( Qt::NoBrush ),
168 textEngine( NULL )
169 {
170 }
171
172 int renderFlags;
173 QString text;
174 QFont font;
175 QColor color;
176 double borderRadius;
177 QPen borderPen;
178 QBrush backgroundBrush;
179
180 QwtText::PaintAttributes paintAttributes;
181 QwtText::LayoutAttributes layoutAttributes;
182
183 const QwtTextEngine* textEngine;
184};
185
186class QwtText::LayoutCache
187{
188 public:
189 void invalidate()
190 {
191 textSize = QSizeF();
192 }
193
194 QFont font;
195 QSizeF textSize;
196};
197
202{
203 m_data = new PrivateData;
204 m_data->textEngine = textEngine( m_data->text, PlainText );
205
206 m_layoutCache = new LayoutCache;
207}
208
215QwtText::QwtText( const QString& text, QwtText::TextFormat textFormat )
216{
217 m_data = new PrivateData;
218 m_data->text = text;
219 m_data->textEngine = textEngine( text, textFormat );
220
221 m_layoutCache = new LayoutCache;
222}
223
226{
227 m_data = new PrivateData;
228 *m_data = *other.m_data;
229
230 m_layoutCache = new LayoutCache;
231 *m_layoutCache = *other.m_layoutCache;
232}
233
236{
237 delete m_data;
238 delete m_layoutCache;
239}
240
243{
244 *m_data = *other.m_data;
245 *m_layoutCache = *other.m_layoutCache;
246 return *this;
247}
248
250bool QwtText::operator==( const QwtText& other ) const
251{
252 return m_data->renderFlags == other.m_data->renderFlags &&
253 m_data->text == other.m_data->text &&
254 m_data->font == other.m_data->font &&
255 m_data->color == other.m_data->color &&
256 m_data->borderRadius == other.m_data->borderRadius &&
257 m_data->borderPen == other.m_data->borderPen &&
258 m_data->backgroundBrush == other.m_data->backgroundBrush &&
259 m_data->paintAttributes == other.m_data->paintAttributes &&
260 m_data->textEngine == other.m_data->textEngine;
261}
262
264bool QwtText::operator!=( const QwtText& other ) const // invalidate
265{
266 return !( other == *this );
267}
268
277void QwtText::setText( const QString& text,
278 QwtText::TextFormat textFormat )
279{
280 m_data->text = text;
281 m_data->textEngine = textEngine( text, textFormat );
282 m_layoutCache->invalidate();
283}
284
289QString QwtText::text() const
290{
291 return m_data->text;
292}
293
304void QwtText::setRenderFlags( int renderFlags )
305{
306 if ( renderFlags != m_data->renderFlags )
307 {
308 m_data->renderFlags = renderFlags;
309 m_layoutCache->invalidate();
310 }
311}
312
318{
319 return m_data->renderFlags;
320}
321
329void QwtText::setFont( const QFont& font )
330{
331 m_data->font = font;
332 setPaintAttribute( PaintUsingTextFont );
333}
334
336QFont QwtText::font() const
337{
338 return m_data->font;
339}
340
350QFont QwtText::usedFont( const QFont& defaultFont ) const
351{
352 if ( m_data->paintAttributes & PaintUsingTextFont )
353 return m_data->font;
354
355 return defaultFont;
356}
357
365void QwtText::setColor( const QColor& color )
366{
367 m_data->color = color;
368 setPaintAttribute( PaintUsingTextColor );
369}
370
372QColor QwtText::color() const
373{
374 return m_data->color;
375}
376
386QColor QwtText::usedColor( const QColor& defaultColor ) const
387{
388 if ( m_data->paintAttributes & PaintUsingTextColor )
389 return m_data->color;
390
391 return defaultColor;
392}
393
400void QwtText::setBorderRadius( double radius )
401{
402 m_data->borderRadius = qwtMaxF( 0.0, radius );
403}
404
410{
411 return m_data->borderRadius;
412}
413
420void QwtText::setBorderPen( const QPen& pen )
421{
422 m_data->borderPen = pen;
423 setPaintAttribute( PaintBackground );
424}
425
431{
432 return m_data->borderPen;
433}
434
441void QwtText::setBackgroundBrush( const QBrush& brush )
442{
443 m_data->backgroundBrush = brush;
444 setPaintAttribute( PaintBackground );
445}
446
452{
453 return m_data->backgroundBrush;
454}
455
467{
468 if ( on )
469 m_data->paintAttributes |= attribute;
470 else
471 m_data->paintAttributes &= ~attribute;
472}
473
483{
484 return m_data->paintAttributes & attribute;
485}
486
495{
496 if ( on )
497 m_data->layoutAttributes |= attribute;
498 else
499 m_data->layoutAttributes &= ~attribute;
500}
501
511{
512 return m_data->layoutAttributes | attribute;
513}
514
522double QwtText::heightForWidth( double width ) const
523{
524 return heightForWidth( width, QFont() );
525}
526
535double QwtText::heightForWidth( double width, const QFont& defaultFont ) const
536{
537 // We want to calculate in screen metrics. So
538 // we need a font that uses screen metrics
539
540 const QFont font = QwtPainter::scaledFont( usedFont( defaultFont ) );
541
542 double h = 0;
543
544 if ( m_data->layoutAttributes & MinimumLayout )
545 {
546 double left, right, top, bottom;
547 m_data->textEngine->textMargins( font, m_data->text,
548 left, right, top, bottom );
549
550 h = m_data->textEngine->heightForWidth(
551 font, m_data->renderFlags, m_data->text,
552 width + left + right );
553
554 h -= top + bottom;
555 }
556 else
557 {
558 h = m_data->textEngine->heightForWidth(
559 font, m_data->renderFlags, m_data->text, width );
560 }
561
562 return h;
563}
564
570QSizeF QwtText::textSize() const
571{
572 return textSize( QFont() );
573}
574
581QSizeF QwtText::textSize( const QFont& defaultFont ) const
582{
583 // We want to calculate in screen metrics. So
584 // we need a font that uses screen metrics
585
586 const QFont font = QwtPainter::scaledFont( usedFont( defaultFont ) );
587
588 if ( !m_layoutCache->textSize.isValid()
589 || m_layoutCache->font != font )
590 {
591 m_layoutCache->textSize = m_data->textEngine->textSize(
592 font, m_data->renderFlags, m_data->text );
593 m_layoutCache->font = font;
594 }
595
596 QSizeF sz = m_layoutCache->textSize;
597
598 if ( m_data->layoutAttributes & MinimumLayout )
599 {
600 double left, right, top, bottom;
601 m_data->textEngine->textMargins( font, m_data->text,
602 left, right, top, bottom );
603 sz -= QSizeF( left + right, top + bottom );
604 }
605
606 return sz;
607}
608
615void QwtText::draw( QPainter* painter, const QRectF& rect ) const
616{
617 if ( m_data->paintAttributes & PaintBackground )
618 {
619 if ( m_data->borderPen != Qt::NoPen ||
620 m_data->backgroundBrush != Qt::NoBrush )
621 {
622 painter->save();
623
624 painter->setPen( m_data->borderPen );
625 painter->setBrush( m_data->backgroundBrush );
626
627 if ( m_data->borderRadius == 0 )
628 {
629 QwtPainter::drawRect( painter, rect );
630 }
631 else
632 {
633 painter->setRenderHint( QPainter::Antialiasing, true );
634 painter->drawRoundedRect( rect,
635 m_data->borderRadius, m_data->borderRadius );
636 }
637
638 painter->restore();
639 }
640 }
641
642 painter->save();
643
644 if ( m_data->paintAttributes & PaintUsingTextFont )
645 {
646 painter->setFont( m_data->font );
647 }
648
649 if ( m_data->paintAttributes & PaintUsingTextColor )
650 {
651 if ( m_data->color.isValid() )
652 painter->setPen( m_data->color );
653 }
654
655 QRectF expandedRect = rect;
656 if ( m_data->layoutAttributes & MinimumLayout )
657 {
658 // We want to calculate in screen metrics. So
659 // we need a font that uses screen metrics
660
661 const QFont font = QwtPainter::scaledFont( painter->font() );
662
663 double left, right, top, bottom;
664 m_data->textEngine->textMargins(
665 font, m_data->text, left, right, top, bottom );
666
667 expandedRect.setTop( rect.top() - top );
668 expandedRect.setBottom( rect.bottom() + bottom );
669 expandedRect.setLeft( rect.left() - left );
670 expandedRect.setRight( rect.right() + right );
671 }
672
673 m_data->textEngine->draw( painter, expandedRect,
674 m_data->renderFlags, m_data->text );
675
676 painter->restore();
677}
678
694const QwtTextEngine* QwtText::textEngine( const QString& text,
695 QwtText::TextFormat format )
696{
697 return TextEngineDict::dict().textEngine( text, format );
698}
699
714 QwtTextEngine* engine )
715{
716 TextEngineDict::dict().setTextEngine( format, engine );
717}
718
728{
729 return TextEngineDict::dict().textEngine( format );
730}
731
733bool QwtText::isNull() const
734{
735 return m_data->text.isNull();
736}
737
740{
741 return m_data->text.isEmpty();
742}
743
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
static QFont scaledFont(const QFont &, const QPaintDevice *=NULL)
A text engine for plain texts.
A text engine for Qt rich texts.
Abstract base class for rendering text strings.
virtual bool mightRender(const QString &text) const =0
A class representing a text.
Definition qwt_text.h:52
static const QwtTextEngine * textEngine(const QString &text, QwtText::TextFormat=AutoText)
Definition qwt_text.cpp:694
LayoutAttribute
Layout Attributes The layout attributes affects some aspects of the layout of the text.
Definition qwt_text.h:133
bool operator==(const QwtText &) const
Relational operator.
Definition qwt_text.cpp:250
QBrush backgroundBrush() const
Definition qwt_text.cpp:451
QColor usedColor(const QColor &) const
Definition qwt_text.cpp:386
void setLayoutAttribute(LayoutAttribute, bool on=true)
Definition qwt_text.cpp:494
bool testPaintAttribute(PaintAttribute) const
Definition qwt_text.cpp:482
QSizeF textSize() const
Definition qwt_text.cpp:570
int renderFlags() const
Definition qwt_text.cpp:317
double borderRadius() const
Definition qwt_text.cpp:409
TextFormat
Text format.
Definition qwt_text.h:65
@ AutoText
Definition qwt_text.h:72
@ RichText
Use the Scribe framework (Qt Rich Text) to render the text.
Definition qwt_text.h:78
@ PlainText
Draw the text as it is, using a QwtPlainTextEngine.
Definition qwt_text.h:75
QFont font() const
Return the font.
Definition qwt_text.cpp:336
QColor color() const
Return the pen color, used for painting the text.
Definition qwt_text.cpp:372
void setBorderRadius(double)
Definition qwt_text.cpp:400
QFlags< LayoutAttribute > LayoutAttributes
Definition qwt_text.h:143
PaintAttribute
Paint Attributes.
Definition qwt_text.h:115
void setText(const QString &, QwtText::TextFormat textFormat=AutoText)
Definition qwt_text.cpp:277
bool isEmpty() const
Definition qwt_text.cpp:739
void setPaintAttribute(PaintAttribute, bool on=true)
Definition qwt_text.cpp:466
bool operator!=(const QwtText &) const
Relational operator.
Definition qwt_text.cpp:264
~QwtText()
Destructor.
Definition qwt_text.cpp:235
void setColor(const QColor &)
Definition qwt_text.cpp:365
void setBorderPen(const QPen &)
Definition qwt_text.cpp:420
void setFont(const QFont &)
Definition qwt_text.cpp:329
QwtText & operator=(const QwtText &)
Assignment operator.
Definition qwt_text.cpp:242
bool testLayoutAttribute(LayoutAttribute) const
Definition qwt_text.cpp:510
void draw(QPainter *painter, const QRectF &rect) const
Definition qwt_text.cpp:615
QString text() const
Definition qwt_text.cpp:289
bool isNull() const
Definition qwt_text.cpp:733
QFlags< PaintAttribute > PaintAttributes
Definition qwt_text.h:126
static void setTextEngine(QwtText::TextFormat, QwtTextEngine *)
Definition qwt_text.cpp:713
void setBackgroundBrush(const QBrush &)
Definition qwt_text.cpp:441
QPen borderPen() const
Definition qwt_text.cpp:430
double heightForWidth(double width) const
Definition qwt_text.cpp:522
void setRenderFlags(int)
Change the render flags.
Definition qwt_text.cpp:304
QFont usedFont(const QFont &) const
Definition qwt_text.cpp:350