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 #define USE_LABEL 1
00038 #ifdef USE_LABEL
00039 #include <qlabel.h>
00040 #else
00041 #include <qtextobject.h>
00042 #endif
00043 #include <qtextdocument.h>
00044 #include <qabstracttextdocumentlayout.h>
00045
00046 class QwtRichTextDocument: public QTextDocument
00047 {
00048 public:
00049 QwtRichTextDocument(const QString &text, const QFont &font)
00050 {
00051 setUndoRedoEnabled(false);
00052 setDefaultFont(font);
00053 setHtml(text);
00054
00055
00056 (void)documentLayout();
00057 }
00058 };
00059
00060 #endif
00061
00062 class QwtPlainTextEngine::PrivateData
00063 {
00064 public:
00065 int effectiveAscent(const QFont &font) const
00066 {
00067 const QString fontKey = font.key();
00068
00069 QMap<QString, int>::const_iterator it =
00070 d_ascentCache.find(fontKey);
00071 if ( it == d_ascentCache.end() )
00072 {
00073 int ascent = findAscent(font);
00074 it = d_ascentCache.insert(fontKey, ascent);
00075 }
00076
00077 return (*it);
00078 }
00079
00080 private:
00081 int findAscent(const QFont &font) const
00082 {
00083 static const QString dummy("E");
00084 static const QColor white(Qt::white);
00085
00086 const QFontMetrics fm(font);
00087 QPixmap pm(fm.width(dummy), fm.height());
00088 pm.fill(white);
00089
00090 QPainter p(&pm);
00091 p.setFont(font);
00092 p.drawText(0, 0, pm.width(), pm.height(), 0, dummy);
00093 p.end();
00094
00095 #if QT_VERSION < 0x040000
00096 const QImage img = pm.convertToImage();
00097 #else
00098 const QImage img = pm.toImage();
00099 #endif
00100
00101 int row = 0;
00102 for ( row = 0; row < img.height(); row++ )
00103 {
00104 const QRgb *line = (const QRgb *)img.scanLine(row);
00105
00106 const int w = pm.width();
00107 for ( int col = 0; col < w; col++ )
00108 {
00109 if ( line[col] != white.rgb() )
00110 return fm.ascent() - row + 1;
00111 }
00112 }
00113
00114 return fm.ascent();
00115 }
00116
00117 mutable QMap<QString, int> d_ascentCache;
00118 };
00119
00120
00121 QwtTextEngine::QwtTextEngine()
00122 {
00123 }
00124
00125 QwtTextEngine::~QwtTextEngine()
00126 {
00127 }
00128
00129 void QwtTextEngine::textMargins(const QFont &, const QString &,
00130 int &left, int &right, int &top, int &bottom)
00131 {
00132 left = right = top = bottom = 0;
00133 }
00134
00135 QwtPlainTextEngine::QwtPlainTextEngine()
00136 {
00137 d_data = new PrivateData;
00138 }
00139
00140 QwtPlainTextEngine::~QwtPlainTextEngine()
00141 {
00142 delete d_data;
00143 }
00144
00145 int QwtPlainTextEngine::heightForWidth(const QFont& font, int flags,
00146 const QString& text, int width) const
00147 {
00148 const QFontMetrics fm(font);
00149 const QRect rect = fm.boundingRect(
00150 0, 0, width, QWIDGETSIZE_MAX, flags, text);
00151
00152 return rect.height();
00153 }
00154
00155 QSize QwtPlainTextEngine::textSize(const QFont &font,
00156 int flags, const QString& text) const
00157 {
00158 const QFontMetrics fm(font);
00159 const QRect rect = fm.boundingRect(
00160 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX, flags, text);
00161
00162 return rect.size();
00163 }
00164
00165 void QwtPlainTextEngine::textMargins(const QFont &font, const QString &,
00166 int &left, int &right, int &top, int &bottom)
00167 {
00168 left = right = top = 0;
00169
00170 const QFontMetrics fm(font);
00171 top = fm.ascent() - d_data->effectiveAscent(font);
00172 bottom = fm.descent() + 1;
00173 }
00174
00175 void QwtPlainTextEngine::draw(QPainter *painter, const QRect &rect,
00176 int flags, const QString& text) const
00177 {
00178 QwtPainter::drawText(painter, rect, flags, text);
00179 }
00180
00181 bool QwtPlainTextEngine::mightRender(const QString &) const
00182 {
00183 return true;
00184 }
00185
00186
00187 #ifndef QT_NO_RICHTEXT
00188
00189 QwtRichTextEngine::QwtRichTextEngine()
00190 {
00191 }
00192
00193 int QwtRichTextEngine::heightForWidth(const QFont& font, int flags,
00194 const QString& text, int width) const
00195 {
00196 QwtRichTextDocument doc(taggedText(text, flags), font);
00197
00198 #if QT_VERSION < 0x040000
00199 doc.setWidth(width);
00200 const int h = doc.height();
00201 #else
00202 doc.setPageSize(QSize(width, QWIDGETSIZE_MAX));
00203 const int h = qRound(doc.documentLayout()->documentSize().height());
00204 #endif
00205 return h;
00206 }
00207
00208 QSize QwtRichTextEngine::textSize(const QFont &font,
00209 int flags, const QString& text) const
00210 {
00211 QwtRichTextDocument doc(taggedText(text, flags), font);
00212
00213 #if QT_VERSION < 0x040000
00214 doc.setWidth(QWIDGETSIZE_MAX);
00215
00216 int w = doc.widthUsed();
00217 int h = doc.height();
00218 #else
00219 #if USE_LABEL
00220
00221
00222
00223
00224
00225
00226
00227
00228 static int off = 0;
00229 static QLabel *label = NULL;
00230 if ( label == NULL )
00231 {
00232 label = new QLabel;
00233 label->hide();
00234
00235 const char *s = "XXXXX";
00236 label->setText(s);
00237 int w1 = label->sizeHint().width();
00238 const QFontMetrics fm(label->font());
00239 int w2 = fm.width(s);
00240 off = w1 - w2;
00241 }
00242 label->setFont(doc.defaultFont());
00243 label->setText(text);
00244
00245 int w = qwtMax(label->sizeHint().width() - off, 0);
00246 doc.setPageSize(QSize(w, QWIDGETSIZE_MAX));
00247
00248 int h = qRound(doc.documentLayout()->documentSize().height());
00249 #else
00250 QTextLayout *layout = doc.begin().layout();
00251 layout->beginLayout();
00252 for(qreal y = 0;;)
00253 {
00254 QTextLine line = layout->createLine();
00255 if (!line.isValid())
00256 break;
00257 line.setPosition(QPointF(0, y));
00258 y += line.height();
00259 }
00260 layout->endLayout();
00261
00262 int w = qRound(layout->maximumWidth());
00263 int h = qRound(layout->boundingRect().height());
00264
00265 h += QFontMetrics(font).descent() + 4;
00266 w += 2 * 4;
00267 #endif
00268 #endif
00269
00270 return QSize(w, h);
00271 }
00272
00273 void QwtRichTextEngine::draw(QPainter *painter, const QRect &rect,
00274 int flags, const QString& text) const
00275 {
00276 QwtRichTextDocument doc(taggedText(text, flags), painter->font());
00277 QwtPainter::drawSimpleRichText(painter, rect, flags, doc);
00278 }
00279
00281 QString QwtRichTextEngine::taggedText(const QString &text, int flags) const
00282 {
00283 QString richText = text;
00284
00285
00286 if (flags & Qt::AlignJustify)
00287 {
00288 richText.prepend(QString::fromLatin1("<div align=\"justify\">"));
00289 richText.append(QString::fromLatin1("</div>"));
00290 }
00291 else if (flags & Qt::AlignRight)
00292 {
00293 richText.prepend(QString::fromLatin1("<div align=\"right\">"));
00294 richText.append(QString::fromLatin1("</div>"));
00295 }
00296 else if (flags & Qt::AlignHCenter)
00297 {
00298 richText.prepend(QString::fromLatin1("<div align=\"center\">"));
00299 richText.append(QString::fromLatin1("</div>"));
00300 }
00301
00302 return richText;
00303 }
00304
00305 bool QwtRichTextEngine::mightRender(const QString &text) const
00306 {
00307 #if QT_VERSION < 0x040000
00308 return QStyleSheet::mightBeRichText(text);
00309 #else
00310 return Qt::mightBeRichText(text);
00311 #endif
00312 }
00313
00314 #endif // !QT_NO_RICHTEXT