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

Last change on this file since 10456 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
RevLine 
[4271]1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
[8127]4 * Copyright (C) 2002 Uwe Rathmann
[4271]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{
[9383]64 for ( EngineMap::const_iterator it = d_map.constBegin();
65 it != d_map.constEnd(); ++it )
[4271]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
[9383]110 EngineMap::const_iterator it = d_map.constFind( format );
111 if ( it != d_map.constEnd() )
[4271]112 {
[9383]113 delete this->engine( it );
[4271]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 ),
[8127]138 borderRadius( 0 ),
139 borderPen( Qt::NoPen ),
[4271]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;
[8127]151 double borderRadius;
152 QPen borderPen;
[4271]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 &&
[8127]220 d_data->borderRadius == other.d_data->borderRadius &&
221 d_data->borderPen == other.d_data->borderPen &&
[4271]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/*!
[8127]250 \return Text as QString.
[4271]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
[8127]263 \param renderFlags Bitwise OR of the flags used like in QPainter::drawText()
[4271]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/*!
[8127]306 Return the font of the text, if it has one.
307 Otherwise return defaultFont.
[4271]308
[8127]309 \param defaultFont Default font
310 \return Font used for drawing the text
311
312 \sa setFont(), font(), PaintAttributes
[4271]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/*!
[8127]323 Set the pen color used for drawing the text.
[4271]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
[8127]346 \return Color used for drawing the text
347
[4271]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/*!
[8127]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/*!
[4271]379 Set the background pen
380
381 \param pen Background pen
[8127]382 \sa borderPen(), setBackgroundBrush()
[4271]383*/
[8127]384void QwtText::setBorderPen( const QPen &pen )
[4271]385{
[8127]386 d_data->borderPen = pen;
[4271]387 setPaintAttribute( PaintBackground );
388}
389
390/*!
391 \return Background pen
[8127]392 \sa setBorderPen(), backgroundBrush()
[4271]393*/
[8127]394QPen QwtText::borderPen() const
[4271]395{
[8127]396 return d_data->borderPen;
[4271]397}
398
399/*!
400 Set the background brush
401
402 \param brush Background brush
[8127]403 \sa backgroundBrush(), setBorderPen()
[4271]404*/
405void QwtText::setBackgroundBrush( const QBrush &brush )
406{
407 d_data->backgroundBrush = brush;
408 setPaintAttribute( PaintBackground );
409}
410
411/*!
412 \return Background brush
[8127]413 \sa setBackgroundBrush(), borderPen()
[4271]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(),
[8127]427 setBorderPen() and setBackgroundBrush()
[4271]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
[8127]521 \return Calculated size
[4271]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 {
[8127]561 if ( d_data->borderPen != Qt::NoPen ||
[4271]562 d_data->backgroundBrush != Qt::NoBrush )
563 {
564 painter->save();
[8127]565
566 painter->setPen( d_data->borderPen );
[4271]567 painter->setBrush( d_data->backgroundBrush );
[8127]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
[4271]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
[8127]626 returns true. If there is none QwtPlainTextEngine is returned.
[4271]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
[8127]633
634 \return Corresponding text engine
[4271]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.