Qwt User's Guide 6.2.0

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
24 static QwtText qwtStringToText( const QString& text )
25 {
26 return QwtText( text );
27 }
28
29 #endif
30
31 namespace
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
47 namespace
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
160 class 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
186 class QwtText::LayoutCache
187 {
188 public:
189 void invalidate()
190 {
191 textSize = QSizeF();
192 }
193
194 QFont font;
195 QSizeF textSize;
196 };
197
201 QwtText::QwtText()
202 {
203 m_data = new PrivateData;
204 m_data->textEngine = textEngine( m_data->text, PlainText );
205
206 m_layoutCache = new LayoutCache;
207 }
208
215 QwtText::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
225 QwtText::QwtText( const QwtText& other )
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
235 QwtText::~QwtText()
236 {
237 delete m_data;
238 delete m_layoutCache;
239 }
240
242 QwtText& QwtText::operator=( const QwtText& other )
243 {
244 *m_data = *other.m_data;
245 *m_layoutCache = *other.m_layoutCache;
246 return *this;
247 }
248
250 bool 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
264 bool QwtText::operator!=( const QwtText& other ) const // invalidate
265 {
266 return !( other == *this );
267 }
268
277 void 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
289 QString QwtText::text() const
290 {
291 return m_data->text;
292 }
293
304 void QwtText::setRenderFlags( int renderFlags )
305 {
306 if ( renderFlags != m_data->renderFlags )
307 {
308 m_data->renderFlags = renderFlags;
309 m_layoutCache->invalidate();
310 }
311 }
312
317 int QwtText::renderFlags() const
318 {
319 return m_data->renderFlags;
320 }
321
329 void QwtText::setFont( const QFont& font )
330 {
331 m_data->font = font;
332 setPaintAttribute( PaintUsingTextFont );
333 }
334
336 QFont QwtText::font() const
337 {
338 return m_data->font;
339 }
340
350 QFont QwtText::usedFont( const QFont& defaultFont ) const
351 {
352 if ( m_data->paintAttributes & PaintUsingTextFont )
353 return m_data->font;
354
355 return defaultFont;
356 }
357
365 void QwtText::setColor( const QColor& color )
366 {
367 m_data->color = color;
368 setPaintAttribute( PaintUsingTextColor );
369 }
370
372 QColor QwtText::color() const
373 {
374 return m_data->color;
375 }
376
386 QColor QwtText::usedColor( const QColor& defaultColor ) const
387 {
388 if ( m_data->paintAttributes & PaintUsingTextColor )
389 return m_data->color;
390
391 return defaultColor;
392 }
393
400 void QwtText::setBorderRadius( double radius )
401 {
402 m_data->borderRadius = qwtMaxF( 0.0, radius );
403 }
404
409 double QwtText::borderRadius() const
410 {
411 return m_data->borderRadius;
412 }
413
420 void QwtText::setBorderPen( const QPen& pen )
421 {
422 m_data->borderPen = pen;
423 setPaintAttribute( PaintBackground );
424 }
425
430 QPen QwtText::borderPen() const
431 {
432 return m_data->borderPen;
433 }
434
441 void QwtText::setBackgroundBrush( const QBrush& brush )
442 {
443 m_data->backgroundBrush = brush;
444 setPaintAttribute( PaintBackground );
445 }
446
451 QBrush QwtText::backgroundBrush() const
452 {
453 return m_data->backgroundBrush;
454 }
455
466 void QwtText::setPaintAttribute( PaintAttribute attribute, bool on )
467 {
468 if ( on )
469 m_data->paintAttributes |= attribute;
470 else
471 m_data->paintAttributes &= ~attribute;
472 }
473
482 bool QwtText::testPaintAttribute( PaintAttribute attribute ) const
483 {
484 return m_data->paintAttributes & attribute;
485 }
486
494 void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on )
495 {
496 if ( on )
497 m_data->layoutAttributes |= attribute;
498 else
499 m_data->layoutAttributes &= ~attribute;
500 }
501
510 bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const
511 {
512 return m_data->layoutAttributes | attribute;
513 }
514
522 double QwtText::heightForWidth( double width ) const
523 {
524 return heightForWidth( width, QFont() );
525 }
526
535 double 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
570 QSizeF QwtText::textSize() const
571 {
572 return textSize( QFont() );
573 }
574
581 QSizeF 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
615 void 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
694 const QwtTextEngine* QwtText::textEngine( const QString& text,
695 QwtText::TextFormat format )
696 {
697 return TextEngineDict::dict().textEngine( text, format );
698 }
699
713 void QwtText::setTextEngine( QwtText::TextFormat format,
714 QwtTextEngine* engine )
715 {
716 TextEngineDict::dict().setTextEngine( format, engine );
717 }
718
727 const QwtTextEngine* QwtText::textEngine( QwtText::TextFormat format )
728 {
729 return TextEngineDict::dict().textEngine( format );
730 }
731
733 bool QwtText::isNull() const
734 {
735 return m_data->text.isNull();
736 }
737
739 bool QwtText::isEmpty() const
740 {
741 return m_data->text.isEmpty();
742 }
743
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