00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qpainter.h>
00013 #include <qpixmap.h>
00014 #include <qimage.h>
00015 #include <qmap.h>
00016 #include <qwidget.h>
00017 #include "qwt_math.h"
00018 #include "qwt_painter.h"
00019 #include "qwt_text_engine.h"
00020
00021 #if QT_VERSION < 0x040000
00022
00023 #include <qsimplerichtext.h>
00024 #include <qstylesheet.h>
00025
00026 class QwtRichTextDocument: public QSimpleRichText
00027 {
00028 public:
00029 QwtRichTextDocument(const QString &text, const QFont &font):
00030 QSimpleRichText(text, font)
00031 {
00032 }
00033 };
00034
00035 #else // QT_VERSION >= 0x040000
00036
00037 #if QT_VERSION < 0x040200
00038 #define USE_LABEL 1
00039 #endif
00040
00041 #ifdef USE_LABEL
00042 #include <qlabel.h>
00043 #else
00044 #include <qtextobject.h>
00045 #endif
00046 #include <qtextdocument.h>
00047 #include <qabstracttextdocumentlayout.h>
00048
00049 class QwtRichTextDocument: public QTextDocument
00050 {
00051 public:
00052 QwtRichTextDocument(const QString &text, const QFont &font)
00053 {
00054 setUndoRedoEnabled(false);
00055 setDefaultFont(font);
00056 setHtml(text);
00057
00058
00059 (void)documentLayout();
00060 }
00061 };
00062
00063 #endif
00064
00065 class QwtPlainTextEngine::PrivateData
00066 {
00067 public:
00068 int effectiveAscent(const QFont &font) const
00069 {
00070 const QString fontKey = font.key();
00071
00072 QMap<QString, int>::const_iterator it =
00073 d_ascentCache.find(fontKey);
00074 if ( it == d_ascentCache.end() )
00075 {
00076 int ascent = findAscent(font);
00077 it = d_ascentCache.insert(fontKey, ascent);
00078 }
00079
00080 return (*it);
00081 }
00082
00083 private:
00084 int findAscent(const QFont &font) const
00085 {
00086 static const QString dummy("E");
00087 static const QColor white(Qt::white);
00088
00089 const QFontMetrics fm(font);
00090 QPixmap pm(fm.width(dummy), fm.height());
00091 pm.fill(white);
00092
00093 QPainter p(&pm);
00094 p.setFont(font);
00095 p.drawText(0, 0, pm.width(), pm.height(), 0, dummy);
00096 p.end();
00097
00098 #if QT_VERSION < 0x040000
00099 const QImage img = pm.convertToImage();
00100 #else
00101 const QImage img = pm.toImage();
00102 #endif
00103
00104 int row = 0;
00105 for ( row = 0; row < img.height(); row++ )
00106 {
00107 const QRgb *line = (const QRgb *)img.scanLine(row);
00108
00109 const int w = pm.width();
00110 for ( int col = 0; col < w; col++ )
00111 {
00112 if ( line[col] != white.rgb() )
00113 return fm.ascent() - row + 1;
00114 }
00115 }
00116
00117 return fm.ascent();
00118 }
00119
00120 mutable QMap<QString, int> d_ascentCache;
00121 };
00122
00124 QwtTextEngine::QwtTextEngine()
00125 {
00126 }
00127
00129 QwtTextEngine::~QwtTextEngine()
00130 {
00131 }
00132
00134 QwtPlainTextEngine::QwtPlainTextEngine()
00135 {
00136 d_data = new PrivateData;
00137 }
00138
00140 QwtPlainTextEngine::~QwtPlainTextEngine()
00141 {
00142 delete d_data;
00143 }
00144
00155 int QwtPlainTextEngine::heightForWidth(const QFont& font, int flags,
00156 const QString& text, int width) const
00157 {
00158 const QFontMetrics fm(font);
00159 const QRect rect = fm.boundingRect(
00160 0, 0, width, QWIDGETSIZE_MAX, flags, text);
00161
00162 return rect.height();
00163 }
00164
00174 QSize QwtPlainTextEngine::textSize(const QFont &font,
00175 int flags, const QString& text) const
00176 {
00177 const QFontMetrics fm(font);
00178 const QRect rect = fm.boundingRect(
00179 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX, flags, text);
00180
00181 return rect.size();
00182 }
00183
00193 void QwtPlainTextEngine::textMargins(const QFont &font, const QString &,
00194 int &left, int &right, int &top, int &bottom) const
00195 {
00196 left = right = top = 0;
00197
00198 const QFontMetrics fm(font);
00199 top = fm.ascent() - d_data->effectiveAscent(font);
00200 bottom = fm.descent() + 1;
00201 }
00202
00213 void QwtPlainTextEngine::draw(QPainter *painter, const QRect &rect,
00214 int flags, const QString& text) const
00215 {
00216 QwtPainter::drawText(painter, rect, flags, text);
00217 }
00218
00223 bool QwtPlainTextEngine::mightRender(const QString &) const
00224 {
00225 return true;
00226 }
00227
00228 #ifndef QT_NO_RICHTEXT
00229
00231 QwtRichTextEngine::QwtRichTextEngine()
00232 {
00233 }
00234
00245 int QwtRichTextEngine::heightForWidth(const QFont& font, int flags,
00246 const QString& text, int width) const
00247 {
00248 QwtRichTextDocument doc(taggedText(text, flags), font);
00249
00250 #if QT_VERSION < 0x040000
00251 doc.setWidth(width);
00252 const int h = doc.height();
00253 #else
00254 doc.setPageSize(QSize(width, QWIDGETSIZE_MAX));
00255 const int h = qRound(doc.documentLayout()->documentSize().height());
00256 #endif
00257 return h;
00258 }
00259
00270 QSize QwtRichTextEngine::textSize(const QFont &font,
00271 int flags, const QString& text) const
00272 {
00273 QwtRichTextDocument doc(taggedText(text, flags), font);
00274
00275 #if QT_VERSION < 0x040000
00276 doc.setWidth(QWIDGETSIZE_MAX);
00277
00278 int w = doc.widthUsed();
00279 int h = doc.height();
00280 #else
00281 #if USE_LABEL
00282
00283
00284
00285
00286
00287
00288
00289
00290 static int off = 0;
00291 static QLabel *label = NULL;
00292 if ( label == NULL )
00293 {
00294 label = new QLabel;
00295 label->hide();
00296
00297 const char *s = "XXXXX";
00298 label->setText(s);
00299 int w1 = label->sizeHint().width();
00300 const QFontMetrics fm(label->font());
00301 int w2 = fm.width(s);
00302 off = w1 - w2;
00303 }
00304 label->setFont(doc.defaultFont());
00305 label->setText(text);
00306
00307 int w = qwtMax(label->sizeHint().width() - off, 0);
00308 doc.setPageSize(QSize(w, QWIDGETSIZE_MAX));
00309
00310 int h = qRound(doc.documentLayout()->documentSize().height());
00311 #else
00312 QTextLayout *layout = doc.begin().layout();
00313 layout->beginLayout();
00314 for(qreal y = 0;;)
00315 {
00316 QTextLine line = layout->createLine();
00317 if (!line.isValid())
00318 break;
00319 line.setPosition(QPointF(0, y));
00320 y += line.height();
00321 }
00322 layout->endLayout();
00323
00324 int w = qRound(layout->maximumWidth());
00325 int h = qRound(layout->boundingRect().height());
00326
00327 h += QFontMetrics(font).descent() + 4;
00328 w += 2 * 4;
00329 #endif
00330 #endif
00331
00332 return QSize(w, h);
00333 }
00334
00343 void QwtRichTextEngine::draw(QPainter *painter, const QRect &rect,
00344 int flags, const QString& text) const
00345 {
00346 QwtRichTextDocument doc(taggedText(text, flags), painter->font());
00347 QwtPainter::drawSimpleRichText(painter, rect, flags, doc);
00348 }
00349
00358 QString QwtRichTextEngine::taggedText(const QString &text, int flags) const
00359 {
00360 QString richText = text;
00361
00362
00363 if (flags & Qt::AlignJustify)
00364 {
00365 richText.prepend(QString::fromLatin1("<div align=\"justify\">"));
00366 richText.append(QString::fromLatin1("</div>"));
00367 }
00368 else if (flags & Qt::AlignRight)
00369 {
00370 richText.prepend(QString::fromLatin1("<div align=\"right\">"));
00371 richText.append(QString::fromLatin1("</div>"));
00372 }
00373 else if (flags & Qt::AlignHCenter)
00374 {
00375 richText.prepend(QString::fromLatin1("<div align=\"center\">"));
00376 richText.append(QString::fromLatin1("</div>"));
00377 }
00378
00379 return richText;
00380 }
00381
00388 bool QwtRichTextEngine::mightRender(const QString &text) const
00389 {
00390 #if QT_VERSION < 0x040000
00391 return QStyleSheet::mightBeRichText(text);
00392 #else
00393 return Qt::mightBeRichText(text);
00394 #endif
00395 }
00396
00405 void QwtRichTextEngine::textMargins(const QFont &, const QString &,
00406 int &left, int &right, int &top, int &bottom) const
00407 {
00408 left = right = top = bottom = 0;
00409 }
00410
00411 #endif // !QT_NO_RICHTEXT