source: ntrip/trunk/BNC/qwt/qwt_text.cpp@ 10502

Last change on this file since 10502 was 9383, checked in by stoecker, 4 years ago

update to qwt verion 6.1.1 to fix build with newer Qt5

File size: 15.5 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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 <qmap.h>
14#include <qfont.h>
15#include <qcolor.h>
16#include <qpen.h>
17#include <qbrush.h>
18#include <qpainter.h>
19#include <qapplication.h>
20#include <qdesktopwidget.h>
21#include <qmath.h>
22
23class QwtTextEngineDict
24{
25public:
26 static QwtTextEngineDict &dict();
27
28 void setTextEngine( QwtText::TextFormat, QwtTextEngine * );
29
30 const QwtTextEngine *textEngine( QwtText::TextFormat ) const;
31 const QwtTextEngine *textEngine( const QString &,
32 QwtText::TextFormat ) const;
33
34private:
35 QwtTextEngineDict();
36 ~QwtTextEngineDict();
37
38 typedef QMap<int, QwtTextEngine *> EngineMap;
39
40 inline const QwtTextEngine *engine( EngineMap::const_iterator &it ) const
41 {
42 return it.value();
43 }
44
45 EngineMap d_map;
46};
47
48QwtTextEngineDict &QwtTextEngineDict::dict()
49{
50 static QwtTextEngineDict engineDict;
51 return engineDict;
52}
53
54QwtTextEngineDict::QwtTextEngineDict()
55{
56 d_map.insert( QwtText::PlainText, new QwtPlainTextEngine() );
57#ifndef QT_NO_RICHTEXT
58 d_map.insert( QwtText::RichText, new QwtRichTextEngine() );
59#endif
60}
61
62QwtTextEngineDict::~QwtTextEngineDict()
63{
64 for ( EngineMap::const_iterator it = d_map.constBegin();
65 it != d_map.constEnd(); ++it )
66 {
67 const QwtTextEngine *textEngine = engine( it );
68 delete textEngine;
69 }
70}
71
72const QwtTextEngine *QwtTextEngineDict::textEngine( const QString& text,
73 QwtText::TextFormat format ) const
74{
75 if ( format == QwtText::AutoText )
76 {
77 for ( EngineMap::const_iterator it = d_map.begin();
78 it != d_map.end(); ++it )
79 {
80 if ( it.key() != QwtText::PlainText )
81 {
82 const QwtTextEngine *e = engine( it );
83 if ( e && e->mightRender( text ) )
84 return e;
85 }
86 }
87 }
88
89 EngineMap::const_iterator it = d_map.find( format );
90 if ( it != d_map.end() )
91 {
92 const QwtTextEngine *e = engine( it );
93 if ( e )
94 return e;
95 }
96
97 it = d_map.find( QwtText::PlainText );
98 return engine( it );
99}
100
101void QwtTextEngineDict::setTextEngine( QwtText::TextFormat format,
102 QwtTextEngine *engine )
103{
104 if ( format == QwtText::AutoText )
105 return;
106
107 if ( format == QwtText::PlainText && engine == NULL )
108 return;
109
110 EngineMap::const_iterator it = d_map.constFind( format );
111 if ( it != d_map.constEnd() )
112 {
113 delete this->engine( it );
114 d_map.remove( format );
115 }
116
117 if ( engine != NULL )
118 d_map.insert( format, engine );
119}
120
121const QwtTextEngine *QwtTextEngineDict::textEngine(
122 QwtText::TextFormat format ) const
123{
124 const QwtTextEngine *e = NULL;
125
126 EngineMap::const_iterator it = d_map.find( format );
127 if ( it != d_map.end() )
128 e = engine( it );
129
130 return e;
131}
132
133class QwtText::PrivateData
134{
135public:
136 PrivateData():
137 renderFlags( Qt::AlignCenter ),
138 borderRadius( 0 ),
139 borderPen( Qt::NoPen ),
140 backgroundBrush( Qt::NoBrush ),
141 paintAttributes( 0 ),
142 layoutAttributes( 0 ),
143 textEngine( NULL )
144 {
145 }
146
147 int renderFlags;
148 QString text;
149 QFont font;
150 QColor color;
151 double borderRadius;
152 QPen borderPen;
153 QBrush backgroundBrush;
154
155 QwtText::PaintAttributes paintAttributes;
156 QwtText::LayoutAttributes layoutAttributes;
157
158 const QwtTextEngine *textEngine;
159};
160
161class QwtText::LayoutCache
162{
163public:
164 void invalidate()
165 {
166 textSize = QSizeF();
167 }
168
169 QFont font;
170 QSizeF textSize;
171};
172
173/*!
174 Constructor
175
176 \param text Text content
177 \param textFormat Text format
178*/
179QwtText::QwtText( const QString &text, QwtText::TextFormat textFormat )
180{
181 d_data = new PrivateData;
182 d_data->text = text;
183 d_data->textEngine = textEngine( text, textFormat );
184
185 d_layoutCache = new LayoutCache;
186}
187
188//! Copy constructor
189QwtText::QwtText( const QwtText &other )
190{
191 d_data = new PrivateData;
192 *d_data = *other.d_data;
193
194 d_layoutCache = new LayoutCache;
195 *d_layoutCache = *other.d_layoutCache;
196}
197
198//! Destructor
199QwtText::~QwtText()
200{
201 delete d_data;
202 delete d_layoutCache;
203}
204
205//! Assignment operator
206QwtText &QwtText::operator=( const QwtText & other )
207{
208 *d_data = *other.d_data;
209 *d_layoutCache = *other.d_layoutCache;
210 return *this;
211}
212
213//! Relational operator
214bool QwtText::operator==( const QwtText &other ) const
215{
216 return d_data->renderFlags == other.d_data->renderFlags &&
217 d_data->text == other.d_data->text &&
218 d_data->font == other.d_data->font &&
219 d_data->color == other.d_data->color &&
220 d_data->borderRadius == other.d_data->borderRadius &&
221 d_data->borderPen == other.d_data->borderPen &&
222 d_data->backgroundBrush == other.d_data->backgroundBrush &&
223 d_data->paintAttributes == other.d_data->paintAttributes &&
224 d_data->textEngine == other.d_data->textEngine;
225}
226
227//! Relational operator
228bool QwtText::operator!=( const QwtText &other ) const // invalidate
229{
230 return !( other == *this );
231}
232
233/*!
234 Assign a new text content
235
236 \param text Text content
237 \param textFormat Text format
238
239 \sa text()
240*/
241void QwtText::setText( const QString &text,
242 QwtText::TextFormat textFormat )
243{
244 d_data->text = text;
245 d_data->textEngine = textEngine( text, textFormat );
246 d_layoutCache->invalidate();
247}
248
249/*!
250 \return Text as QString.
251 \sa setText()
252*/
253QString QwtText::text() const
254{
255 return d_data->text;
256}
257
258/*!
259 \brief Change the render flags
260
261 The default setting is Qt::AlignCenter
262
263 \param renderFlags Bitwise OR of the flags used like in QPainter::drawText()
264
265 \sa renderFlags(), QwtTextEngine::draw()
266 \note Some renderFlags might have no effect, depending on the text format.
267*/
268void QwtText::setRenderFlags( int renderFlags )
269{
270 if ( renderFlags != d_data->renderFlags )
271 {
272 d_data->renderFlags = renderFlags;
273 d_layoutCache->invalidate();
274 }
275}
276
277/*!
278 \return Render flags
279 \sa setRenderFlags()
280*/
281int QwtText::renderFlags() const
282{
283 return d_data->renderFlags;
284}
285
286/*!
287 Set the font.
288
289 \param font Font
290 \note Setting the font might have no effect, when
291 the text contains control sequences for setting fonts.
292*/
293void QwtText::setFont( const QFont &font )
294{
295 d_data->font = font;
296 setPaintAttribute( PaintUsingTextFont );
297}
298
299//! Return the font.
300QFont QwtText::font() const
301{
302 return d_data->font;
303}
304
305/*!
306 Return the font of the text, if it has one.
307 Otherwise return defaultFont.
308
309 \param defaultFont Default font
310 \return Font used for drawing the text
311
312 \sa setFont(), font(), PaintAttributes
313*/
314QFont QwtText::usedFont( const QFont &defaultFont ) const
315{
316 if ( d_data->paintAttributes & PaintUsingTextFont )
317 return d_data->font;
318
319 return defaultFont;
320}
321
322/*!
323 Set the pen color used for drawing the text.
324
325 \param color Color
326 \note Setting the color might have no effect, when
327 the text contains control sequences for setting colors.
328*/
329void QwtText::setColor( const QColor &color )
330{
331 d_data->color = color;
332 setPaintAttribute( PaintUsingTextColor );
333}
334
335//! Return the pen color, used for painting the text
336QColor QwtText::color() const
337{
338 return d_data->color;
339}
340
341/*!
342 Return the color of the text, if it has one.
343 Otherwise return defaultColor.
344
345 \param defaultColor Default color
346 \return Color used for drawing the text
347
348 \sa setColor(), color(), PaintAttributes
349*/
350QColor QwtText::usedColor( const QColor &defaultColor ) const
351{
352 if ( d_data->paintAttributes & PaintUsingTextColor )
353 return d_data->color;
354
355 return defaultColor;
356}
357
358/*!
359 Set the radius for the corners of the border frame
360
361 \param radius Radius of a rounded corner
362 \sa borderRadius(), setBorderPen(), setBackgroundBrush()
363*/
364void QwtText::setBorderRadius( double radius )
365{
366 d_data->borderRadius = qMax( 0.0, radius );
367}
368
369/*!
370 \return Radius for the corners of the border frame
371 \sa setBorderRadius(), borderPen(), backgroundBrush()
372*/
373double QwtText::borderRadius() const
374{
375 return d_data->borderRadius;
376}
377
378/*!
379 Set the background pen
380
381 \param pen Background pen
382 \sa borderPen(), setBackgroundBrush()
383*/
384void QwtText::setBorderPen( const QPen &pen )
385{
386 d_data->borderPen = pen;
387 setPaintAttribute( PaintBackground );
388}
389
390/*!
391 \return Background pen
392 \sa setBorderPen(), backgroundBrush()
393*/
394QPen QwtText::borderPen() const
395{
396 return d_data->borderPen;
397}
398
399/*!
400 Set the background brush
401
402 \param brush Background brush
403 \sa backgroundBrush(), setBorderPen()
404*/
405void QwtText::setBackgroundBrush( const QBrush &brush )
406{
407 d_data->backgroundBrush = brush;
408 setPaintAttribute( PaintBackground );
409}
410
411/*!
412 \return Background brush
413 \sa setBackgroundBrush(), borderPen()
414*/
415QBrush QwtText::backgroundBrush() const
416{
417 return d_data->backgroundBrush;
418}
419
420/*!
421 Change a paint attribute
422
423 \param attribute Paint attribute
424 \param on On/Off
425
426 \note Used by setFont(), setColor(),
427 setBorderPen() and setBackgroundBrush()
428 \sa testPaintAttribute()
429*/
430void QwtText::setPaintAttribute( PaintAttribute attribute, bool on )
431{
432 if ( on )
433 d_data->paintAttributes |= attribute;
434 else
435 d_data->paintAttributes &= ~attribute;
436}
437
438/*!
439 Test a paint attribute
440
441 \param attribute Paint attribute
442 \return true, if attribute is enabled
443
444 \sa setPaintAttribute()
445*/
446bool QwtText::testPaintAttribute( PaintAttribute attribute ) const
447{
448 return d_data->paintAttributes & attribute;
449}
450
451/*!
452 Change a layout attribute
453
454 \param attribute Layout attribute
455 \param on On/Off
456 \sa testLayoutAttribute()
457*/
458void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on )
459{
460 if ( on )
461 d_data->layoutAttributes |= attribute;
462 else
463 d_data->layoutAttributes &= ~attribute;
464}
465
466/*!
467 Test a layout attribute
468
469 \param attribute Layout attribute
470 \return true, if attribute is enabled
471
472 \sa setLayoutAttribute()
473*/
474bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const
475{
476 return d_data->layoutAttributes | attribute;
477}
478
479/*!
480 Find the height for a given width
481
482 \param defaultFont Font, used for the calculation if the text has no font
483 \param width Width
484
485 \return Calculated height
486*/
487double QwtText::heightForWidth( double width, const QFont &defaultFont ) const
488{
489 // We want to calculate in screen metrics. So
490 // we need a font that uses screen metrics
491
492 const QFont font( usedFont( defaultFont ), QApplication::desktop() );
493
494 double h = 0;
495
496 if ( d_data->layoutAttributes & MinimumLayout )
497 {
498 double left, right, top, bottom;
499 d_data->textEngine->textMargins( font, d_data->text,
500 left, right, top, bottom );
501
502 h = d_data->textEngine->heightForWidth(
503 font, d_data->renderFlags, d_data->text,
504 width + left + right );
505
506 h -= top + bottom;
507 }
508 else
509 {
510 h = d_data->textEngine->heightForWidth(
511 font, d_data->renderFlags, d_data->text, width );
512 }
513
514 return h;
515}
516
517/*!
518 Returns the size, that is needed to render text
519
520 \param defaultFont Font of the text
521 \return Calculated size
522*/
523QSizeF QwtText::textSize( const QFont &defaultFont ) const
524{
525 // We want to calculate in screen metrics. So
526 // we need a font that uses screen metrics
527
528 const QFont font( usedFont( defaultFont ), QApplication::desktop() );
529
530 if ( !d_layoutCache->textSize.isValid()
531 || d_layoutCache->font != font )
532 {
533 d_layoutCache->textSize = d_data->textEngine->textSize(
534 font, d_data->renderFlags, d_data->text );
535 d_layoutCache->font = font;
536 }
537
538 QSizeF sz = d_layoutCache->textSize;
539
540 if ( d_data->layoutAttributes & MinimumLayout )
541 {
542 double left, right, top, bottom;
543 d_data->textEngine->textMargins( font, d_data->text,
544 left, right, top, bottom );
545 sz -= QSizeF( left + right, top + bottom );
546 }
547
548 return sz;
549}
550
551/*!
552 Draw a text into a rectangle
553
554 \param painter Painter
555 \param rect Rectangle
556*/
557void QwtText::draw( QPainter *painter, const QRectF &rect ) const
558{
559 if ( d_data->paintAttributes & PaintBackground )
560 {
561 if ( d_data->borderPen != Qt::NoPen ||
562 d_data->backgroundBrush != Qt::NoBrush )
563 {
564 painter->save();
565
566 painter->setPen( d_data->borderPen );
567 painter->setBrush( d_data->backgroundBrush );
568
569 if ( d_data->borderRadius == 0 )
570 {
571 QwtPainter::drawRect( painter, rect );
572 }
573 else
574 {
575 painter->setRenderHint( QPainter::Antialiasing, true );
576 painter->drawRoundedRect( rect,
577 d_data->borderRadius, d_data->borderRadius );
578 }
579
580 painter->restore();
581 }
582 }
583
584 painter->save();
585
586 if ( d_data->paintAttributes & PaintUsingTextFont )
587 {
588 painter->setFont( d_data->font );
589 }
590
591 if ( d_data->paintAttributes & PaintUsingTextColor )
592 {
593 if ( d_data->color.isValid() )
594 painter->setPen( d_data->color );
595 }
596
597 QRectF expandedRect = rect;
598 if ( d_data->layoutAttributes & MinimumLayout )
599 {
600 // We want to calculate in screen metrics. So
601 // we need a font that uses screen metrics
602
603 const QFont font( painter->font(), QApplication::desktop() );
604
605 double left, right, top, bottom;
606 d_data->textEngine->textMargins(
607 font, d_data->text, left, right, top, bottom );
608
609 expandedRect.setTop( rect.top() - top );
610 expandedRect.setBottom( rect.bottom() + bottom );
611 expandedRect.setLeft( rect.left() - left );
612 expandedRect.setRight( rect.right() + right );
613 }
614
615 d_data->textEngine->draw( painter, expandedRect,
616 d_data->renderFlags, d_data->text );
617
618 painter->restore();
619}
620
621/*!
622 Find the text engine for a text format
623
624 In case of QwtText::AutoText the first text engine
625 (beside QwtPlainTextEngine) is returned, where QwtTextEngine::mightRender
626 returns true. If there is none QwtPlainTextEngine is returned.
627
628 If no text engine is registered for the format QwtPlainTextEngine
629 is returnd.
630
631 \param text Text, needed in case of AutoText
632 \param format Text format
633
634 \return Corresponding text engine
635*/
636const QwtTextEngine *QwtText::textEngine( const QString &text,
637 QwtText::TextFormat format )
638{
639 return QwtTextEngineDict::dict().textEngine( text, format );
640}
641
642/*!
643 Assign/Replace a text engine for a text format
644
645 With setTextEngine it is possible to extend Qwt with
646 other types of text formats.
647
648 For QwtText::PlainText it is not allowed to assign a engine == NULL.
649
650 \param format Text format
651 \param engine Text engine
652
653 \sa QwtMathMLTextEngine
654 \warning Using QwtText::AutoText does nothing.
655*/
656void QwtText::setTextEngine( QwtText::TextFormat format,
657 QwtTextEngine *engine )
658{
659 QwtTextEngineDict::dict().setTextEngine( format, engine );
660}
661
662/*!
663 \brief Find the text engine for a text format
664
665 textEngine can be used to find out if a text format is supported.
666
667 \param format Text format
668 \return The text engine, or NULL if no engine is available.
669*/
670const QwtTextEngine *QwtText::textEngine( QwtText::TextFormat format )
671{
672 return QwtTextEngineDict::dict().textEngine( format );
673}
Note: See TracBrowser for help on using the repository browser.