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

Last change on this file since 8840 was 8127, checked in by stoecker, 7 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

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