1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2003 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
*****************************************************************************/
18
#include "qwt_painter.h"
19
#include "qwt_text_engine.h"
21
#if QT_VERSION < 0x040000
23
#include <qsimplerichtext.h>
24
#include <qstylesheet.h>
26
class QwtRichTextDocument: public QSimpleRichText
29
QwtRichTextDocument(const QString &text, const QFont &font):
30
QSimpleRichText(text, font)
35
#else // QT_VERSION >= 0x040000
37
#if QT_VERSION < 0x040200
44
#include <qtextobject.h>
46
#include <qtextdocument.h>
47
#include <qabstracttextdocumentlayout.h>
49
class QwtRichTextDocument: public QTextDocument
52
QwtRichTextDocument(const QString &text, const QFont &font)
54
setUndoRedoEnabled(false);
58
// make sure we have a document layout
59
(void)documentLayout();
65
class QwtPlainTextEngine::PrivateData
68
int effectiveAscent(const QFont &font) const
70
const QString fontKey = font.key();
72
QMap<QString, int>::const_iterator it =
73
d_ascentCache.find(fontKey);
74
if ( it == d_ascentCache.end() )
76
int ascent = findAscent(font);
77
it = d_ascentCache.insert(fontKey, ascent);
84
int findAscent(const QFont &font) const
86
static const QString dummy("E");
87
static const QColor white(Qt::white);
89
const QFontMetrics fm(font);
90
QPixmap pm(fm.width(dummy), fm.height());
95
p.drawText(0, 0, pm.width(), pm.height(), 0, dummy);
98
#if QT_VERSION < 0x040000
99
const QImage img = pm.convertToImage();
101
const QImage img = pm.toImage();
105
for ( row = 0; row < img.height(); row++ )
107
const QRgb *line = (const QRgb *)img.scanLine(row);
109
const int w = pm.width();
110
for ( int col = 0; col < w; col++ )
112
if ( line[col] != white.rgb() )
113
return fm.ascent() - row + 1;
120
mutable QMap<QString, int> d_ascentCache;
124
QwtTextEngine::QwtTextEngine()
129
QwtTextEngine::~QwtTextEngine()
134
QwtPlainTextEngine::QwtPlainTextEngine()
136
d_data = new PrivateData;
140
QwtPlainTextEngine::~QwtPlainTextEngine()
146
Find the height for a given width
148
\param font Font of the text
149
\param flags Bitwise OR of the flags used like in QPainter::drawText
150
\param text Text to be rendered
153
\return Calculated height
155
int QwtPlainTextEngine::heightForWidth(const QFont& font, int flags,
156
const QString& text, int width) const
158
const QFontMetrics fm(font);
159
const QRect rect = fm.boundingRect(
160
0, 0, width, QWIDGETSIZE_MAX, flags, text);
162
return rect.height();
166
Returns the size, that is needed to render text
168
\param font Font of the text
169
\param flags Bitwise OR of the flags used like in QPainter::drawText
170
\param text Text to be rendered
172
\return Caluclated size
174
QSize QwtPlainTextEngine::textSize(const QFont &font,
175
int flags, const QString& text) const
177
const QFontMetrics fm(font);
178
const QRect rect = fm.boundingRect(
179
0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX, flags, text);
185
Return margins around the texts
187
\param font Font of the text
189
\param right Return 0
190
\param top Return value for the top margin
191
\param bottom Return value for the bottom margin
193
void QwtPlainTextEngine::textMargins(const QFont &font, const QString &,
194
int &left, int &right, int &top, int &bottom) const
196
left = right = top = 0;
198
const QFontMetrics fm(font);
199
top = fm.ascent() - d_data->effectiveAscent(font);
200
bottom = fm.descent() + 1;
204
\brief Draw the text in a clipping rectangle
206
A wrapper for QPainter::drawText.
208
\param painter Painter
209
\param rect Clipping rectangle
210
\param flags Bitwise OR of the flags used like in QPainter::drawText
211
\param text Text to be rendered
213
void QwtPlainTextEngine::draw(QPainter *painter, const QRect &rect,
214
int flags, const QString& text) const
216
QwtPainter::drawText(painter, rect, flags, text);
220
Test if a string can be rendered by this text engine.
221
\return Always true. All texts can be rendered by QwtPlainTextEngine
223
bool QwtPlainTextEngine::mightRender(const QString &) const
228
#ifndef QT_NO_RICHTEXT
231
QwtRichTextEngine::QwtRichTextEngine()
236
Find the height for a given width
238
\param font Font of the text
239
\param flags Bitwise OR of the flags used like in QPainter::drawText
240
\param text Text to be rendered
243
\return Calculated height
245
int QwtRichTextEngine::heightForWidth(const QFont& font, int flags,
246
const QString& text, int width) const
248
QwtRichTextDocument doc(taggedText(text, flags), font);
250
#if QT_VERSION < 0x040000
252
const int h = doc.height();
254
doc.setPageSize(QSize(width, QWIDGETSIZE_MAX));
255
const int h = qRound(doc.documentLayout()->documentSize().height());
261
Returns the size, that is needed to render text
263
\param font Font of the text
264
\param flags Bitwise OR of the flags used like in QPainter::drawText
265
\param text Text to be rendered
267
\return Caluclated size
270
QSize QwtRichTextEngine::textSize(const QFont &font,
271
int flags, const QString& text) const
273
QwtRichTextDocument doc(taggedText(text, flags), font);
275
#if QT_VERSION < 0x040000
276
doc.setWidth(QWIDGETSIZE_MAX);
278
int w = doc.widthUsed();
279
int h = doc.height();
283
Unfortunately offering the bounding rect calculation in the
284
API of QTextDocument has been forgotten in Qt <= 4.1.x. It
285
is planned to come with Qt 4.2.x.
286
In the meantime we need a hack with a temporary QLabel,
287
to reengineer the internal calculations.
291
static QLabel *label = NULL;
297
const char *s = "XXXXX";
299
int w1 = label->sizeHint().width();
300
const QFontMetrics fm(label->font());
301
int w2 = fm.width(s);
304
label->setFont(doc.defaultFont());
305
label->setText(text);
307
int w = qwtMax(label->sizeHint().width() - off, 0);
308
doc.setPageSize(QSize(w, QWIDGETSIZE_MAX));
310
int h = qRound(doc.documentLayout()->documentSize().height());
312
QTextLayout *layout = doc.begin().layout();
313
layout->beginLayout();
316
QTextLine line = layout->createLine();
319
line.setPosition(QPointF(0, y));
324
int w = qRound(layout->maximumWidth());
325
int h = qRound(layout->boundingRect().height());
327
h += QFontMetrics(font).descent() + 4;
336
Draw the text in a clipping rectangle
338
\param painter Painter
339
\param rect Clipping rectangle
340
\param flags Bitwise OR of the flags like in for QPainter::drawText
341
\param text Text to be rendered
343
void QwtRichTextEngine::draw(QPainter *painter, const QRect &rect,
344
int flags, const QString& text) const
346
QwtRichTextDocument doc(taggedText(text, flags), painter->font());
347
QwtPainter::drawSimpleRichText(painter, rect, flags, doc);
351
Wrap text into <div align=...> </div> tags according flags
354
\param flags Bitwise OR of the flags like in for QPainter::drawText
358
QString QwtRichTextEngine::taggedText(const QString &text, int flags) const
360
QString richText = text;
362
// By default QSimpleRichText is Qt::AlignLeft
363
if (flags & Qt::AlignJustify)
365
richText.prepend(QString::fromLatin1("<div align=\"justify\">"));
366
richText.append(QString::fromLatin1("</div>"));
368
else if (flags & Qt::AlignRight)
370
richText.prepend(QString::fromLatin1("<div align=\"right\">"));
371
richText.append(QString::fromLatin1("</div>"));
373
else if (flags & Qt::AlignHCenter)
375
richText.prepend(QString::fromLatin1("<div align=\"center\">"));
376
richText.append(QString::fromLatin1("</div>"));
383
Test if a string can be rendered by this text engine
385
\param text Text to be tested
386
\return QStyleSheet::mightBeRichText(text);
388
bool QwtRichTextEngine::mightRender(const QString &text) const
390
#if QT_VERSION < 0x040000
391
return QStyleSheet::mightBeRichText(text);
393
return Qt::mightBeRichText(text);
398
Return margins around the texts
401
\param right Return 0
403
\param bottom Return 0
405
void QwtRichTextEngine::textMargins(const QFont &, const QString &,
406
int &left, int &right, int &top, int &bottom) const
408
left = right = top = bottom = 0;
411
#endif // !QT_NO_RICHTEXT