1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
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 *****************************************************************************/
11 #include "qwt_painter.h"
12 #include "qwt_text_engine.h"
19 #include <qapplication.h>
20 #include <qdesktopwidget.h>
23 class QwtTextEngineDict
26 static QwtTextEngineDict
&dict();
28 void setTextEngine( QwtText::TextFormat
, QwtTextEngine
* );
30 const QwtTextEngine
*textEngine( QwtText::TextFormat
) const;
31 const QwtTextEngine
*textEngine( const QString
&,
32 QwtText::TextFormat
) const;
38 typedef QMap
<int, QwtTextEngine
*> EngineMap
;
40 inline const QwtTextEngine
*engine( EngineMap::const_iterator
&it
) const
48 QwtTextEngineDict
&QwtTextEngineDict::dict()
50 static QwtTextEngineDict engineDict
;
54 QwtTextEngineDict::QwtTextEngineDict()
56 d_map
.insert( QwtText::PlainText
, new QwtPlainTextEngine() );
57 #ifndef QT_NO_RICHTEXT
58 d_map
.insert( QwtText::RichText
, new QwtRichTextEngine() );
62 QwtTextEngineDict::~QwtTextEngineDict()
64 for ( EngineMap::const_iterator it
= d_map
.begin();
65 it
!= d_map
.end(); ++it
)
67 const QwtTextEngine
*textEngine
= engine( it
);
72 const QwtTextEngine
*QwtTextEngineDict::textEngine( const QString
& text
,
73 QwtText::TextFormat format
) const
75 if ( format
== QwtText::AutoText
)
77 for ( EngineMap::const_iterator it
= d_map
.begin();
78 it
!= d_map
.end(); ++it
)
80 if ( it
.key() != QwtText::PlainText
)
82 const QwtTextEngine
*e
= engine( it
);
83 if ( e
&& e
->mightRender( text
) )
89 EngineMap::const_iterator it
= d_map
.find( format
);
90 if ( it
!= d_map
.end() )
92 const QwtTextEngine
*e
= engine( it
);
97 it
= d_map
.find( QwtText::PlainText
);
101 void QwtTextEngineDict::setTextEngine( QwtText::TextFormat format
,
102 QwtTextEngine
*engine
)
104 if ( format
== QwtText::AutoText
)
107 if ( format
== QwtText::PlainText
&& engine
== NULL
)
110 EngineMap::const_iterator it
= d_map
.find( format
);
111 if ( it
!= d_map
.end() )
113 const QwtTextEngine
*e
= this->engine( it
);
117 d_map
.remove( format
);
120 if ( engine
!= NULL
)
121 d_map
.insert( format
, engine
);
124 const QwtTextEngine
*QwtTextEngineDict::textEngine(
125 QwtText::TextFormat format
) const
127 const QwtTextEngine
*e
= NULL
;
129 EngineMap::const_iterator it
= d_map
.find( format
);
130 if ( it
!= d_map
.end() )
136 class QwtText::PrivateData
140 renderFlags( Qt::AlignCenter
),
142 borderPen( Qt::NoPen
),
143 backgroundBrush( Qt::NoBrush
),
144 paintAttributes( 0 ),
145 layoutAttributes( 0 ),
156 QBrush backgroundBrush
;
158 QwtText::PaintAttributes paintAttributes
;
159 QwtText::LayoutAttributes layoutAttributes
;
161 const QwtTextEngine
*textEngine
;
164 class QwtText::LayoutCache
179 \param text Text content
180 \param textFormat Text format
182 QwtText::QwtText( const QString
&text
, QwtText::TextFormat textFormat
)
184 d_data
= new PrivateData
;
186 d_data
->textEngine
= textEngine( text
, textFormat
);
188 d_layoutCache
= new LayoutCache
;
192 QwtText::QwtText( const QwtText
&other
)
194 d_data
= new PrivateData
;
195 *d_data
= *other
.d_data
;
197 d_layoutCache
= new LayoutCache
;
198 *d_layoutCache
= *other
.d_layoutCache
;
205 delete d_layoutCache
;
208 //! Assignment operator
209 QwtText
&QwtText::operator=( const QwtText
& other
)
211 *d_data
= *other
.d_data
;
212 *d_layoutCache
= *other
.d_layoutCache
;
216 //! Relational operator
217 bool QwtText::operator==( const QwtText
&other
) const
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
&&
223 d_data
->borderRadius
== other
.d_data
->borderRadius
&&
224 d_data
->borderPen
== other
.d_data
->borderPen
&&
225 d_data
->backgroundBrush
== other
.d_data
->backgroundBrush
&&
226 d_data
->paintAttributes
== other
.d_data
->paintAttributes
&&
227 d_data
->textEngine
== other
.d_data
->textEngine
;
230 //! Relational operator
231 bool QwtText::operator!=( const QwtText
&other
) const // invalidate
233 return !( other
== *this );
237 Assign a new text content
239 \param text Text content
240 \param textFormat Text format
244 void QwtText::setText( const QString
&text
,
245 QwtText::TextFormat textFormat
)
248 d_data
->textEngine
= textEngine( text
, textFormat
);
249 d_layoutCache
->invalidate();
253 \return Text as QString.
256 QString
QwtText::text() const
262 \brief Change the render flags
264 The default setting is Qt::AlignCenter
266 \param renderFlags Bitwise OR of the flags used like in QPainter::drawText()
268 \sa renderFlags(), QwtTextEngine::draw()
269 \note Some renderFlags might have no effect, depending on the text format.
271 void QwtText::setRenderFlags( int renderFlags
)
273 if ( renderFlags
!= d_data
->renderFlags
)
275 d_data
->renderFlags
= renderFlags
;
276 d_layoutCache
->invalidate();
284 int QwtText::renderFlags() const
286 return d_data
->renderFlags
;
293 \note Setting the font might have no effect, when
294 the text contains control sequences for setting fonts.
296 void QwtText::setFont( const QFont
&font
)
299 setPaintAttribute( PaintUsingTextFont
);
303 QFont
QwtText::font() const
309 Return the font of the text, if it has one.
310 Otherwise return defaultFont.
312 \param defaultFont Default font
313 \return Font used for drawing the text
315 \sa setFont(), font(), PaintAttributes
317 QFont
QwtText::usedFont( const QFont
&defaultFont
) const
319 if ( d_data
->paintAttributes
& PaintUsingTextFont
)
326 Set the pen color used for drawing the text.
329 \note Setting the color might have no effect, when
330 the text contains control sequences for setting colors.
332 void QwtText::setColor( const QColor
&color
)
334 d_data
->color
= color
;
335 setPaintAttribute( PaintUsingTextColor
);
338 //! Return the pen color, used for painting the text
339 QColor
QwtText::color() const
341 return d_data
->color
;
345 Return the color of the text, if it has one.
346 Otherwise return defaultColor.
348 \param defaultColor Default color
349 \return Color used for drawing the text
351 \sa setColor(), color(), PaintAttributes
353 QColor
QwtText::usedColor( const QColor
&defaultColor
) const
355 if ( d_data
->paintAttributes
& PaintUsingTextColor
)
356 return d_data
->color
;
362 Set the radius for the corners of the border frame
364 \param radius Radius of a rounded corner
365 \sa borderRadius(), setBorderPen(), setBackgroundBrush()
367 void QwtText::setBorderRadius( double radius
)
369 d_data
->borderRadius
= qMax( 0.0, radius
);
373 \return Radius for the corners of the border frame
374 \sa setBorderRadius(), borderPen(), backgroundBrush()
376 double QwtText::borderRadius() const
378 return d_data
->borderRadius
;
382 Set the background pen
384 \param pen Background pen
385 \sa borderPen(), setBackgroundBrush()
387 void QwtText::setBorderPen( const QPen
&pen
)
389 d_data
->borderPen
= pen
;
390 setPaintAttribute( PaintBackground
);
394 \return Background pen
395 \sa setBorderPen(), backgroundBrush()
397 QPen
QwtText::borderPen() const
399 return d_data
->borderPen
;
403 Set the background brush
405 \param brush Background brush
406 \sa backgroundBrush(), setBorderPen()
408 void QwtText::setBackgroundBrush( const QBrush
&brush
)
410 d_data
->backgroundBrush
= brush
;
411 setPaintAttribute( PaintBackground
);
415 \return Background brush
416 \sa setBackgroundBrush(), borderPen()
418 QBrush
QwtText::backgroundBrush() const
420 return d_data
->backgroundBrush
;
424 Change a paint attribute
426 \param attribute Paint attribute
429 \note Used by setFont(), setColor(),
430 setBorderPen() and setBackgroundBrush()
431 \sa testPaintAttribute()
433 void QwtText::setPaintAttribute( PaintAttribute attribute
, bool on
)
436 d_data
->paintAttributes
|= attribute
;
438 d_data
->paintAttributes
&= ~attribute
;
442 Test a paint attribute
444 \param attribute Paint attribute
445 \return true, if attribute is enabled
447 \sa setPaintAttribute()
449 bool QwtText::testPaintAttribute( PaintAttribute attribute
) const
451 return d_data
->paintAttributes
& attribute
;
455 Change a layout attribute
457 \param attribute Layout attribute
459 \sa testLayoutAttribute()
461 void QwtText::setLayoutAttribute( LayoutAttribute attribute
, bool on
)
464 d_data
->layoutAttributes
|= attribute
;
466 d_data
->layoutAttributes
&= ~attribute
;
470 Test a layout attribute
472 \param attribute Layout attribute
473 \return true, if attribute is enabled
475 \sa setLayoutAttribute()
477 bool QwtText::testLayoutAttribute( LayoutAttribute attribute
) const
479 return d_data
->layoutAttributes
| attribute
;
483 Find the height for a given width
485 \param defaultFont Font, used for the calculation if the text has no font
488 \return Calculated height
490 double QwtText::heightForWidth( double width
, const QFont
&defaultFont
) const
492 // We want to calculate in screen metrics. So
493 // we need a font that uses screen metrics
495 const QFont
font( usedFont( defaultFont
), QApplication::desktop() );
499 if ( d_data
->layoutAttributes
& MinimumLayout
)
501 double left
, right
, top
, bottom
;
502 d_data
->textEngine
->textMargins( font
, d_data
->text
,
503 left
, right
, top
, bottom
);
505 h
= d_data
->textEngine
->heightForWidth(
506 font
, d_data
->renderFlags
, d_data
->text
,
507 width
+ left
+ right
);
513 h
= d_data
->textEngine
->heightForWidth(
514 font
, d_data
->renderFlags
, d_data
->text
, width
);
521 Find the height for a given width
523 \param defaultFont Font, used for the calculation if the text has no font
525 \return Calculated height
529 Returns the size, that is needed to render text
531 \param defaultFont Font of the text
532 \return Caluclated size
534 QSizeF
QwtText::textSize( const QFont
&defaultFont
) const
536 // We want to calculate in screen metrics. So
537 // we need a font that uses screen metrics
539 const QFont
font( usedFont( defaultFont
), QApplication::desktop() );
541 if ( !d_layoutCache
->textSize
.isValid()
542 || d_layoutCache
->font
!= font
)
544 d_layoutCache
->textSize
= d_data
->textEngine
->textSize(
545 font
, d_data
->renderFlags
, d_data
->text
);
546 d_layoutCache
->font
= font
;
549 QSizeF sz
= d_layoutCache
->textSize
;
551 if ( d_data
->layoutAttributes
& MinimumLayout
)
553 double left
, right
, top
, bottom
;
554 d_data
->textEngine
->textMargins( font
, d_data
->text
,
555 left
, right
, top
, bottom
);
556 sz
-= QSizeF( left
+ right
, top
+ bottom
);
563 Draw a text into a rectangle
565 \param painter Painter
566 \param rect Rectangle
568 void QwtText::draw( QPainter
*painter
, const QRectF
&rect
) const
570 if ( d_data
->paintAttributes
& PaintBackground
)
572 if ( d_data
->borderPen
!= Qt::NoPen
||
573 d_data
->backgroundBrush
!= Qt::NoBrush
)
577 painter
->setPen( d_data
->borderPen
);
578 painter
->setBrush( d_data
->backgroundBrush
);
580 if ( d_data
->borderRadius
== 0 )
582 QwtPainter::drawRect( painter
, rect
);
586 painter
->setRenderHint( QPainter::Antialiasing
, true );
587 painter
->drawRoundedRect( rect
,
588 d_data
->borderRadius
, d_data
->borderRadius
);
597 if ( d_data
->paintAttributes
& PaintUsingTextFont
)
599 painter
->setFont( d_data
->font
);
602 if ( d_data
->paintAttributes
& PaintUsingTextColor
)
604 if ( d_data
->color
.isValid() )
605 painter
->setPen( d_data
->color
);
608 QRectF expandedRect
= rect
;
609 if ( d_data
->layoutAttributes
& MinimumLayout
)
611 // We want to calculate in screen metrics. So
612 // we need a font that uses screen metrics
614 const QFont
font( painter
->font(), QApplication::desktop() );
616 double left
, right
, top
, bottom
;
617 d_data
->textEngine
->textMargins(
618 font
, d_data
->text
, left
, right
, top
, bottom
);
620 expandedRect
.setTop( rect
.top() - top
);
621 expandedRect
.setBottom( rect
.bottom() + bottom
);
622 expandedRect
.setLeft( rect
.left() - left
);
623 expandedRect
.setRight( rect
.right() + right
);
626 d_data
->textEngine
->draw( painter
, expandedRect
,
627 d_data
->renderFlags
, d_data
->text
);
633 Find the text engine for a text format
635 In case of QwtText::AutoText the first text engine
636 (beside QwtPlainTextEngine) is returned, where QwtTextEngine::mightRender
637 returns true. If there is none QwtPlainTextEngine is returned.
639 If no text engine is registered for the format QwtPlainTextEngine
642 \param text Text, needed in case of AutoText
643 \param format Text format
645 \return Corresponding text engine
647 const QwtTextEngine
*QwtText::textEngine( const QString
&text
,
648 QwtText::TextFormat format
)
650 return QwtTextEngineDict::dict().textEngine( text
, format
);
654 Assign/Replace a text engine for a text format
656 With setTextEngine it is possible to extend Qwt with
657 other types of text formats.
659 For QwtText::PlainText it is not allowed to assign a engine == NULL.
661 \param format Text format
662 \param engine Text engine
664 \sa QwtMathMLTextEngine
665 \warning Using QwtText::AutoText does nothing.
667 void QwtText::setTextEngine( QwtText::TextFormat format
,
668 QwtTextEngine
*engine
)
670 QwtTextEngineDict::dict().setTextEngine( format
, engine
);
674 \brief Find the text engine for a text format
676 textEngine can be used to find out if a text format is supported.
678 \param format Text format
679 \return The text engine, or NULL if no engine is available.
681 const QwtTextEngine
*QwtText::textEngine( QwtText::TextFormat format
)
683 return QwtTextEngineDict::dict().textEngine( format
);