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

Last change on this file since 6770 was 4271, checked in by mervart, 12 years ago
File size: 14.7 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2003 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.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 ),
141 backgroundPen( Qt::NoPen ),
142 backgroundBrush( Qt::NoBrush ),
143 paintAttributes( 0 ),
144 layoutAttributes( 0 ),
145 textEngine( NULL )
146 {
147 }
148
149 int renderFlags;
150 QString text;
151 QFont font;
152 QColor color;
153 QPen backgroundPen;
154 QBrush backgroundBrush;
155
156 QwtText::PaintAttributes paintAttributes;
157 QwtText::LayoutAttributes layoutAttributes;
158
159 const QwtTextEngine *textEngine;
160};
161
162class QwtText::LayoutCache
163{
164public:
165 void invalidate()
166 {
167 textSize = QSizeF();
168 }
169
170 QFont font;
171 QSizeF textSize;
172};
173
174/*!
175 Constructor
176
177 \param text Text content
178 \param textFormat Text format
179*/
180QwtText::QwtText( const QString &text, QwtText::TextFormat textFormat )
181{
182 d_data = new PrivateData;
183 d_data->text = text;
184 d_data->textEngine = textEngine( text, textFormat );
185
186 d_layoutCache = new LayoutCache;
187}
188
189//! Copy constructor
190QwtText::QwtText( const QwtText &other )
191{
192 d_data = new PrivateData;
193 *d_data = *other.d_data;
194
195 d_layoutCache = new LayoutCache;
196 *d_layoutCache = *other.d_layoutCache;
197}
198
199//! Destructor
200QwtText::~QwtText()
201{
202 delete d_data;
203 delete d_layoutCache;
204}
205
206//! Assignment operator
207QwtText &QwtText::operator=( const QwtText & other )
208{
209 *d_data = *other.d_data;
210 *d_layoutCache = *other.d_layoutCache;
211 return *this;
212}
213
214//! Relational operator
215bool QwtText::operator==( const QwtText &other ) const
216{
217 return d_data->renderFlags == other.d_data->renderFlags &&
218 d_data->text == other.d_data->text &&
219 d_data->font == other.d_data->font &&
220 d_data->color == other.d_data->color &&
221 d_data->backgroundPen == other.d_data->backgroundPen &&
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 the text.
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 \sa setFont(), font(), PaintAttributes
311*/
312QFont QwtText::usedFont( const QFont &defaultFont ) const
313{
314 if ( d_data->paintAttributes & PaintUsingTextFont )
315 return d_data->font;
316
317 return defaultFont;
318}
319
320/*!
321 Set the pen color used for painting the text.
322
323 \param color Color
324 \note Setting the color might have no effect, when
325 the text contains control sequences for setting colors.
326*/
327void QwtText::setColor( const QColor &color )
328{
329 d_data->color = color;
330 setPaintAttribute( PaintUsingTextColor );
331}
332
333//! Return the pen color, used for painting the text
334QColor QwtText::color() const
335{
336 return d_data->color;
337}
338
339/*!
340 Return the color of the text, if it has one.
341 Otherwise return defaultColor.
342
343 \param defaultColor Default color
344 \sa setColor(), color(), PaintAttributes
345*/
346QColor QwtText::usedColor( const QColor &defaultColor ) const
347{
348 if ( d_data->paintAttributes & PaintUsingTextColor )
349 return d_data->color;
350
351 return defaultColor;
352}
353
354/*!
355 Set the background pen
356
357 \param pen Background pen
358 \sa backgroundPen(), setBackgroundBrush()
359*/
360void QwtText::setBackgroundPen( const QPen &pen )
361{
362 d_data->backgroundPen = pen;
363 setPaintAttribute( PaintBackground );
364}
365
366/*!
367 \return Background pen
368 \sa setBackgroundPen(), backgroundBrush()
369*/
370QPen QwtText::backgroundPen() const
371{
372 return d_data->backgroundPen;
373}
374
375/*!
376 Set the background brush
377
378 \param brush Background brush
379 \sa backgroundBrush(), setBackgroundPen()
380*/
381void QwtText::setBackgroundBrush( const QBrush &brush )
382{
383 d_data->backgroundBrush = brush;
384 setPaintAttribute( PaintBackground );
385}
386
387/*!
388 \return Background brush
389 \sa setBackgroundBrush(), backgroundPen()
390*/
391QBrush QwtText::backgroundBrush() const
392{
393 return d_data->backgroundBrush;
394}
395
396/*!
397 Change a paint attribute
398
399 \param attribute Paint attribute
400 \param on On/Off
401
402 \note Used by setFont(), setColor(),
403 setBackgroundPen() and setBackgroundBrush()
404 \sa testPaintAttribute()
405*/
406void QwtText::setPaintAttribute( PaintAttribute attribute, bool on )
407{
408 if ( on )
409 d_data->paintAttributes |= attribute;
410 else
411 d_data->paintAttributes &= ~attribute;
412}
413
414/*!
415 Test a paint attribute
416
417 \param attribute Paint attribute
418 \return true, if attribute is enabled
419
420 \sa setPaintAttribute()
421*/
422bool QwtText::testPaintAttribute( PaintAttribute attribute ) const
423{
424 return d_data->paintAttributes & attribute;
425}
426
427/*!
428 Change a layout attribute
429
430 \param attribute Layout attribute
431 \param on On/Off
432 \sa testLayoutAttribute()
433*/
434void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on )
435{
436 if ( on )
437 d_data->layoutAttributes |= attribute;
438 else
439 d_data->layoutAttributes &= ~attribute;
440}
441
442/*!
443 Test a layout attribute
444
445 \param attribute Layout attribute
446 \return true, if attribute is enabled
447
448 \sa setLayoutAttribute()
449*/
450bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const
451{
452 return d_data->layoutAttributes | attribute;
453}
454
455/*!
456 Find the height for a given width
457
458 \param defaultFont Font, used for the calculation if the text has no font
459 \param width Width
460
461 \return Calculated height
462*/
463double QwtText::heightForWidth( double width, const QFont &defaultFont ) const
464{
465 // We want to calculate in screen metrics. So
466 // we need a font that uses screen metrics
467
468 const QFont font( usedFont( defaultFont ), QApplication::desktop() );
469
470 double h = 0;
471
472 if ( d_data->layoutAttributes & MinimumLayout )
473 {
474 double left, right, top, bottom;
475 d_data->textEngine->textMargins( font, d_data->text,
476 left, right, top, bottom );
477
478 h = d_data->textEngine->heightForWidth(
479 font, d_data->renderFlags, d_data->text,
480 width + left + right );
481
482 h -= top + bottom;
483 }
484 else
485 {
486 h = d_data->textEngine->heightForWidth(
487 font, d_data->renderFlags, d_data->text, width );
488 }
489
490 return h;
491}
492
493/*!
494 Find the height for a given width
495
496 \param defaultFont Font, used for the calculation if the text has no font
497
498 \return Calculated height
499*/
500
501/*!
502 Returns the size, that is needed to render text
503
504 \param defaultFont Font of the text
505 \return Caluclated size
506*/
507QSizeF QwtText::textSize( const QFont &defaultFont ) const
508{
509 // We want to calculate in screen metrics. So
510 // we need a font that uses screen metrics
511
512 const QFont font( usedFont( defaultFont ), QApplication::desktop() );
513
514 if ( !d_layoutCache->textSize.isValid()
515 || d_layoutCache->font != font )
516 {
517 d_layoutCache->textSize = d_data->textEngine->textSize(
518 font, d_data->renderFlags, d_data->text );
519 d_layoutCache->font = font;
520 }
521
522 QSizeF sz = d_layoutCache->textSize;
523
524 if ( d_data->layoutAttributes & MinimumLayout )
525 {
526 double left, right, top, bottom;
527 d_data->textEngine->textMargins( font, d_data->text,
528 left, right, top, bottom );
529 sz -= QSizeF( left + right, top + bottom );
530 }
531
532 return sz;
533}
534
535/*!
536 Draw a text into a rectangle
537
538 \param painter Painter
539 \param rect Rectangle
540*/
541void QwtText::draw( QPainter *painter, const QRectF &rect ) const
542{
543 if ( d_data->paintAttributes & PaintBackground )
544 {
545 if ( d_data->backgroundPen != Qt::NoPen ||
546 d_data->backgroundBrush != Qt::NoBrush )
547 {
548 painter->save();
549 painter->setPen( d_data->backgroundPen );
550 painter->setBrush( d_data->backgroundBrush );
551 QwtPainter::drawRect( painter, rect );
552 painter->restore();
553 }
554 }
555
556 painter->save();
557
558 if ( d_data->paintAttributes & PaintUsingTextFont )
559 {
560 painter->setFont( d_data->font );
561 }
562
563 if ( d_data->paintAttributes & PaintUsingTextColor )
564 {
565 if ( d_data->color.isValid() )
566 painter->setPen( d_data->color );
567 }
568
569 QRectF expandedRect = rect;
570 if ( d_data->layoutAttributes & MinimumLayout )
571 {
572 // We want to calculate in screen metrics. So
573 // we need a font that uses screen metrics
574
575 const QFont font( painter->font(), QApplication::desktop() );
576
577 double left, right, top, bottom;
578 d_data->textEngine->textMargins(
579 font, d_data->text, left, right, top, bottom );
580
581 expandedRect.setTop( rect.top() - top );
582 expandedRect.setBottom( rect.bottom() + bottom );
583 expandedRect.setLeft( rect.left() - left );
584 expandedRect.setRight( rect.right() + right );
585 }
586
587 d_data->textEngine->draw( painter, expandedRect,
588 d_data->renderFlags, d_data->text );
589
590 painter->restore();
591}
592
593/*!
594 Find the text engine for a text format
595
596 In case of QwtText::AutoText the first text engine
597 (beside QwtPlainTextEngine) is returned, where QwtTextEngine::mightRender
598 returns true. If there is none QwtPlainTextEngine is returnd.
599
600 If no text engine is registered for the format QwtPlainTextEngine
601 is returnd.
602
603 \param text Text, needed in case of AutoText
604 \param format Text format
605*/
606const QwtTextEngine *QwtText::textEngine( const QString &text,
607 QwtText::TextFormat format )
608{
609 return QwtTextEngineDict::dict().textEngine( text, format );
610}
611
612/*!
613 Assign/Replace a text engine for a text format
614
615 With setTextEngine it is possible to extend Qwt with
616 other types of text formats.
617
618 For QwtText::PlainText it is not allowed to assign a engine == NULL.
619
620 \param format Text format
621 \param engine Text engine
622
623 \sa QwtMathMLTextEngine
624 \warning Using QwtText::AutoText does nothing.
625*/
626void QwtText::setTextEngine( QwtText::TextFormat format,
627 QwtTextEngine *engine )
628{
629 QwtTextEngineDict::dict().setTextEngine( format, engine );
630}
631
632/*!
633 \brief Find the text engine for a text format
634
635 textEngine can be used to find out if a text format is supported.
636
637 \param format Text format
638 \return The text engine, or NULL if no engine is available.
639*/
640const QwtTextEngine *QwtText::textEngine( QwtText::TextFormat format )
641{
642 return QwtTextEngineDict::dict().textEngine( format );
643}
Note: See TracBrowser for help on using the repository browser.