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 *****************************************************************************/
10 #include "qwt_text_engine.h"
12 #include "qwt_painter.h"
18 #include <qtextobject.h>
19 #include <qtextdocument.h>
20 #include <qabstracttextdocumentlayout.h>
22 static QString
taggedRichText( const QString
&text
, int flags
)
24 QString richText
= text
;
26 // By default QSimpleRichText is Qt::AlignLeft
27 if ( flags
& Qt::AlignJustify
)
29 richText
.prepend( QString::fromLatin1( "<div align=\"justify\">" ) );
30 richText
.append( QString::fromLatin1( "</div>" ) );
32 else if ( flags
& Qt::AlignRight
)
34 richText
.prepend( QString::fromLatin1( "<div align=\"right\">" ) );
35 richText
.append( QString::fromLatin1( "</div>" ) );
37 else if ( flags
& Qt::AlignHCenter
)
39 richText
.prepend( QString::fromLatin1( "<div align=\"center\">" ) );
40 richText
.append( QString::fromLatin1( "</div>" ) );
46 class QwtRichTextDocument
: public QTextDocument
49 QwtRichTextDocument( const QString
&text
, int flags
, const QFont
&font
)
51 setUndoRedoEnabled( false );
52 setDefaultFont( font
);
55 // make sure we have a document layout
56 ( void )documentLayout();
58 QTextOption option
= defaultTextOption();
59 if ( flags
& Qt::TextWordWrap
)
60 option
.setWrapMode( QTextOption::WordWrap
);
62 option
.setWrapMode( QTextOption::NoWrap
);
64 option
.setAlignment( static_cast<Qt::Alignment
>( flags
) );
65 setDefaultTextOption( option
);
67 QTextFrame
*root
= rootFrame();
68 QTextFrameFormat fm
= root
->frameFormat();
72 fm
.setBottomMargin( 0 );
73 fm
.setLeftMargin( 0 );
74 root
->setFrameFormat( fm
);
80 class QwtPlainTextEngine::PrivateData
83 int effectiveAscent( const QFont
&font
) const
85 const QString fontKey
= font
.key();
87 QMap
<QString
, int>::const_iterator it
=
88 d_ascentCache
.find( fontKey
);
89 if ( it
== d_ascentCache
.end() )
91 int ascent
= findAscent( font
);
92 it
= d_ascentCache
.insert( fontKey
, ascent
);
99 int findAscent( const QFont
&font
) const
101 static const QString
dummy( "E" );
102 static const QColor
white( Qt::white
);
104 const QFontMetrics
fm( font
);
105 QPixmap
pm( fm
.width( dummy
), fm
.height() );
110 p
.drawText( 0, 0, pm
.width(), pm
.height(), 0, dummy
);
113 const QImage img
= pm
.toImage();
116 for ( row
= 0; row
< img
.height(); row
++ )
118 const QRgb
*line
= reinterpret_cast<const QRgb
*>(
119 img
.scanLine( row
) );
121 const int w
= pm
.width();
122 for ( int col
= 0; col
< w
; col
++ )
124 if ( line
[col
] != white
.rgb() )
125 return fm
.ascent() - row
+ 1;
132 mutable QMap
<QString
, int> d_ascentCache
;
136 QwtTextEngine::QwtTextEngine()
141 QwtTextEngine::~QwtTextEngine()
146 QwtPlainTextEngine::QwtPlainTextEngine()
148 d_data
= new PrivateData
;
152 QwtPlainTextEngine::~QwtPlainTextEngine()
158 Find the height for a given width
160 \param font Font of the text
161 \param flags Bitwise OR of the flags used like in QPainter::drawText
162 \param text Text to be rendered
165 \return Calculated height
167 double QwtPlainTextEngine::heightForWidth( const QFont
& font
, int flags
,
168 const QString
& text
, double width
) const
170 const QFontMetricsF
fm( font
);
171 const QRectF rect
= fm
.boundingRect(
172 QRectF( 0, 0, width
, QWIDGETSIZE_MAX
), flags
, text
);
174 return rect
.height();
178 Returns the size, that is needed to render text
180 \param font Font of the text
181 \param flags Bitwise OR of the flags used like in QPainter::drawText
182 \param text Text to be rendered
184 \return Calculated size
186 QSizeF
QwtPlainTextEngine::textSize( const QFont
&font
,
187 int flags
, const QString
& text
) const
189 const QFontMetricsF
fm( font
);
190 const QRectF rect
= fm
.boundingRect(
191 QRectF( 0, 0, QWIDGETSIZE_MAX
, QWIDGETSIZE_MAX
), flags
, text
);
197 Return margins around the texts
199 \param font Font of the text
201 \param right Return 0
202 \param top Return value for the top margin
203 \param bottom Return value for the bottom margin
205 void QwtPlainTextEngine::textMargins( const QFont
&font
, const QString
&,
206 double &left
, double &right
, double &top
, double &bottom
) const
208 left
= right
= top
= 0;
210 const QFontMetricsF
fm( font
);
211 top
= fm
.ascent() - d_data
->effectiveAscent( font
);
212 bottom
= fm
.descent();
216 \brief Draw the text in a clipping rectangle
218 A wrapper for QPainter::drawText.
220 \param painter Painter
221 \param rect Clipping rectangle
222 \param flags Bitwise OR of the flags used like in QPainter::drawText
223 \param text Text to be rendered
225 void QwtPlainTextEngine::draw( QPainter
*painter
, const QRectF
&rect
,
226 int flags
, const QString
& text
) const
228 QwtPainter::drawText( painter
, rect
, flags
, text
);
232 Test if a string can be rendered by this text engine.
233 \return Always true. All texts can be rendered by QwtPlainTextEngine
235 bool QwtPlainTextEngine::mightRender( const QString
& ) const
240 #ifndef QT_NO_RICHTEXT
243 QwtRichTextEngine::QwtRichTextEngine()
248 Find the height for a given width
250 \param font Font of the text
251 \param flags Bitwise OR of the flags used like in QPainter::drawText()
252 \param text Text to be rendered
255 \return Calculated height
257 double QwtRichTextEngine::heightForWidth( const QFont
& font
, int flags
,
258 const QString
& text
, double width
) const
260 QwtRichTextDocument
doc( text
, flags
, font
);
262 doc
.setPageSize( QSizeF( width
, QWIDGETSIZE_MAX
) );
263 return doc
.documentLayout()->documentSize().height();
267 Returns the size, that is needed to render text
269 \param font Font of the text
270 \param flags Bitwise OR of the flags used like in QPainter::drawText()
271 \param text Text to be rendered
273 \return Calculated size
276 QSizeF
QwtRichTextEngine::textSize( const QFont
&font
,
277 int flags
, const QString
& text
) const
279 QwtRichTextDocument
doc( text
, flags
, font
);
281 QTextOption option
= doc
.defaultTextOption();
282 if ( option
.wrapMode() != QTextOption::NoWrap
)
284 option
.setWrapMode( QTextOption::NoWrap
);
285 doc
.setDefaultTextOption( option
);
293 Draw the text in a clipping rectangle
295 \param painter Painter
296 \param rect Clipping rectangle
297 \param flags Bitwise OR of the flags like in for QPainter::drawText()
298 \param text Text to be rendered
300 void QwtRichTextEngine::draw( QPainter
*painter
, const QRectF
&rect
,
301 int flags
, const QString
& text
) const
303 QwtRichTextDocument
doc( text
, flags
, painter
->font() );
304 QwtPainter::drawSimpleRichText( painter
, rect
, flags
, doc
);
308 Wrap text into <div align=...> </div> tags according flags
311 \param flags Bitwise OR of the flags like in for QPainter::drawText()
315 QString
QwtRichTextEngine::taggedText( const QString
&text
, int flags
) const
317 return taggedRichText( text
, flags
);
321 Test if a string can be rendered by this text engine
323 \param text Text to be tested
324 \return Qt::mightBeRichText(text);
326 bool QwtRichTextEngine::mightRender( const QString
&text
) const
328 return Qt::mightBeRichText( text
);
332 Return margins around the texts
335 \param right Return 0
337 \param bottom Return 0
339 void QwtRichTextEngine::textMargins( const QFont
&, const QString
&,
340 double &left
, double &right
, double &top
, double &bottom
) const
342 left
= right
= top
= bottom
= 0;
345 #endif // !QT_NO_RICHTEXT