00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qmap.h>
00013 #include <qfont.h>
00014 #include <qcolor.h>
00015 #include <qpen.h>
00016 #include <qbrush.h>
00017 #include <qpainter.h>
00018 #include "qwt_painter.h"
00019 #include "qwt_text_engine.h"
00020 #include "qwt_text.h"
00021 #if QT_VERSION >= 0x040000
00022 #include <QPluginLoader>
00023 #include <qapplication.h>
00024 #include <qdesktopwidget.h>
00025 #include <qdir.h>
00026 #include "qwt_text_plugin.h"
00027 #endif
00028
00029 class QwtTextEngineDict
00030 {
00031 public:
00032 QwtTextEngineDict();
00033 ~QwtTextEngineDict();
00034
00035 const QwtTextEngine *textEngine(QwtText::TextFormat) const;
00036 const QwtTextEngine *textEngine(const QString &,
00037 QwtText::TextFormat) const;
00038
00039 private:
00040 typedef QMap<int, QwtTextEngine *> EngineMap;
00041
00042 inline const QwtTextEngine *engine(EngineMap::const_iterator &it) const
00043 {
00044 #if QT_VERSION < 0x040000
00045 return it.data();
00046 #else
00047 return it.value();
00048 #endif
00049 }
00050
00051 EngineMap d_map;
00052 };
00053
00054 QwtTextEngineDict::QwtTextEngineDict()
00055 {
00056 d_map.insert(QwtText::PlainText, new QwtPlainTextEngine());
00057 #ifndef QT_NO_RICHTEXT
00058 d_map.insert(QwtText::RichText, new QwtRichTextEngine());
00059 #endif
00060
00061 #if QT_VERSION >= 0x040000
00062
00063
00064
00065 const QStringList libPaths = QApplication::libraryPaths();
00066 foreach (QString path, QApplication::libraryPaths())
00067 {
00068 QDir pluginsDir(path);
00069 if ( !pluginsDir.cd("qwttextengines") )
00070 continue;
00071
00072 foreach (QString fileName, pluginsDir.entryList(QDir::Files))
00073 {
00074 QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
00075
00076 QwtTextPlugin *plugin =
00077 qobject_cast<QwtTextPlugin *>(loader.instance());
00078 if (plugin)
00079 {
00080 if ( ::qgetenv("QWT_DEBUG_PLUGINS").toInt() > 0 )
00081 {
00082 qDebug("Qwt Text Plugin loaded: %s\n",
00083 qPrintable(loader.fileName()) );
00084 }
00085 EngineMap::iterator it = d_map.find(plugin->format());
00086 if ( it == d_map.end() )
00087 d_map.insert(plugin->format(), plugin->engine());
00088 }
00089 }
00090 }
00091 #endif // QT_VERSION >= 0x040000
00092 }
00093
00094 QwtTextEngineDict::~QwtTextEngineDict()
00095 {
00096 for ( EngineMap::const_iterator it = d_map.begin();
00097 it != d_map.end(); ++it )
00098 {
00099 QwtTextEngine *textEngine = (QwtTextEngine *)engine(it);
00100 delete textEngine;
00101 }
00102 }
00103
00104 const QwtTextEngine *QwtTextEngineDict::textEngine(const QString& text,
00105 QwtText::TextFormat format) const
00106 {
00107 if ( format == QwtText::AutoText )
00108 {
00109 for ( EngineMap::const_iterator it = d_map.begin();
00110 it != d_map.end(); ++it )
00111 {
00112 if ( it.key() != QwtText::PlainText )
00113 {
00114 const QwtTextEngine *e = engine(it);
00115 if ( e && e->mightRender(text) )
00116 return (QwtTextEngine *)e;
00117 }
00118 }
00119 }
00120
00121 EngineMap::const_iterator it = d_map.find(format);
00122 if ( it != d_map.end() )
00123 {
00124 const QwtTextEngine *e = engine(it);
00125 if ( e )
00126 return e;
00127 }
00128
00129 it = d_map.find(QwtText::PlainText);
00130 return engine(it);
00131 }
00132
00133 const QwtTextEngine *QwtTextEngineDict::textEngine(
00134 QwtText::TextFormat format) const
00135 {
00136 const QwtTextEngine *e = NULL;
00137
00138 EngineMap::const_iterator it = d_map.find(format);
00139 if ( it != d_map.end() )
00140 e = engine(it);
00141
00142 return e;
00143 }
00144
00145 static QwtTextEngineDict *engineDict = NULL;
00146
00147 class QwtText::PrivateData
00148 {
00149 public:
00150 PrivateData():
00151 renderFlags(Qt::AlignCenter),
00152 backgroundPen(Qt::NoPen),
00153 backgroundBrush(Qt::NoBrush),
00154 paintAttributes(0),
00155 layoutAttributes(0),
00156 textEngine(NULL)
00157 {
00158 }
00159
00160 int renderFlags;
00161 QString text;
00162 QFont font;
00163 QColor color;
00164 QPen backgroundPen;
00165 QBrush backgroundBrush;
00166
00167 int paintAttributes;
00168 int layoutAttributes;
00169
00170 const QwtTextEngine *textEngine;
00171 };
00172
00173 class QwtText::LayoutCache
00174 {
00175 public:
00176 void invalidate()
00177 {
00178 textSize = QSize();
00179 }
00180
00181 QFont font;
00182 QSize textSize;
00183 };
00184
00191 QwtText::QwtText(const QString &text, QwtText::TextFormat textFormat)
00192 {
00193 d_data = new PrivateData;
00194 d_data->text = text;
00195 d_data->textEngine = textEngine(text, textFormat);
00196
00197 d_layoutCache = new LayoutCache;
00198 }
00199
00201 QwtText::QwtText(const QwtText &other)
00202 {
00203 d_data = new PrivateData;
00204 *d_data = *other.d_data;
00205
00206 d_layoutCache = new LayoutCache;
00207 *d_layoutCache = *other.d_layoutCache;
00208 }
00209
00211 QwtText::~QwtText()
00212 {
00213 delete d_data;
00214 delete d_layoutCache;
00215 }
00216
00218 QwtText &QwtText::operator=(const QwtText &other)
00219 {
00220 *d_data = *other.d_data;
00221 *d_layoutCache = *other.d_layoutCache;
00222 return *this;
00223 }
00224
00225 int QwtText::operator==(const QwtText &other) const
00226 {
00227 return d_data->renderFlags == other.d_data->renderFlags &&
00228 d_data->text == other.d_data->text &&
00229 d_data->font == other.d_data->font &&
00230 d_data->color == other.d_data->color &&
00231 d_data->backgroundPen == other.d_data->backgroundPen &&
00232 d_data->backgroundBrush == other.d_data->backgroundBrush &&
00233 d_data->paintAttributes == other.d_data->paintAttributes &&
00234 d_data->textEngine == other.d_data->textEngine;
00235 }
00236
00237 int QwtText::operator!=(const QwtText &other) const
00238 {
00239 return !(other == *this);
00240 }
00241
00248 void QwtText::setText(const QString &text,
00249 QwtText::TextFormat textFormat)
00250 {
00251 d_data->text = text;
00252 d_data->textEngine = textEngine(text, textFormat);
00253 d_layoutCache->invalidate();
00254 }
00255
00260 QString QwtText::text() const
00261 {
00262 return d_data->text;
00263 }
00264
00275 void QwtText::setRenderFlags(int renderFlags)
00276 {
00277 if ( renderFlags != d_data->renderFlags )
00278 {
00279 d_data->renderFlags = renderFlags;
00280 d_layoutCache->invalidate();
00281 }
00282 }
00283
00288 int QwtText::renderFlags() const
00289 {
00290 return d_data->renderFlags;
00291 }
00292
00300 void QwtText::setFont(const QFont &font)
00301 {
00302 d_data->font = font;
00303 setPaintAttribute(PaintUsingTextFont);
00304 }
00305
00307 QFont QwtText::font() const
00308 {
00309 return d_data->font;
00310 }
00311
00319 QFont QwtText::usedFont(const QFont &defaultFont) const
00320 {
00321 if ( d_data->paintAttributes & PaintUsingTextFont )
00322 return d_data->font;
00323
00324 return defaultFont;
00325 }
00326
00334 void QwtText::setColor(const QColor &color)
00335 {
00336 d_data->color = color;
00337 setPaintAttribute(PaintUsingTextColor);
00338 }
00339
00341 QColor QwtText::color() const
00342 {
00343 return d_data->color;
00344 }
00345
00353 QColor QwtText::usedColor(const QColor &defaultColor) const
00354 {
00355 if ( d_data->paintAttributes & PaintUsingTextColor )
00356 return d_data->color;
00357
00358 return defaultColor;
00359 }
00360
00367 void QwtText::setBackgroundPen(const QPen &pen)
00368 {
00369 d_data->backgroundPen = pen;
00370 setPaintAttribute(PaintBackground);
00371 }
00372
00377 QPen QwtText::backgroundPen() const
00378 {
00379 return d_data->backgroundPen;
00380 }
00381
00388 void QwtText::setBackgroundBrush(const QBrush &brush)
00389 {
00390 d_data->backgroundBrush = brush;
00391 setPaintAttribute(PaintBackground);
00392 }
00393
00398 QBrush QwtText::backgroundBrush() const
00399 {
00400 return d_data->backgroundBrush;
00401 }
00402
00412 void QwtText::setPaintAttribute(PaintAttribute attribute, bool on)
00413 {
00414 if ( on )
00415 d_data->paintAttributes |= attribute;
00416 else
00417 d_data->paintAttributes &= ~attribute;
00418 }
00419
00428 bool QwtText::testPaintAttribute(PaintAttribute attribute) const
00429 {
00430 return d_data->paintAttributes & attribute;
00431 }
00432
00440 void QwtText::setLayoutAttribute(LayoutAttribute attribute, bool on)
00441 {
00442 if ( on )
00443 d_data->layoutAttributes |= attribute;
00444 else
00445 d_data->layoutAttributes &= ~attribute;
00446 }
00447
00456 bool QwtText::testLayoutAttribute(LayoutAttribute attribute) const
00457 {
00458 return d_data->layoutAttributes | attribute;
00459 }
00460
00469 int QwtText::heightForWidth(int width, const QFont &defaultFont) const
00470 {
00471 const QwtMetricsMap map = QwtPainter::metricsMap();
00472 width = map.layoutToScreenX(width);
00473
00474 #if QT_VERSION < 0x040000
00475 const QFont font = usedFont(defaultFont);
00476 #else
00477
00478
00479
00480 const QFont font(usedFont(defaultFont), QApplication::desktop());
00481 #endif
00482
00483 int h = 0;
00484
00485 if ( d_data->layoutAttributes & MinimumLayout )
00486 {
00487 int left, right, top, bottom;
00488 d_data->textEngine->textMargins(font, d_data->text,
00489 left, right, top, bottom);
00490
00491 h = d_data->textEngine->heightForWidth(
00492 font, d_data->renderFlags, d_data->text,
00493 width + left + right);
00494
00495 h -= top + bottom;
00496 }
00497 else
00498 {
00499 h = d_data->textEngine->heightForWidth(
00500 font, d_data->renderFlags, d_data->text, width);
00501 }
00502
00503 h = map.screenToLayoutY(h);
00504 return h;
00505 }
00506
00521 QSize QwtText::textSize(const QFont &defaultFont) const
00522 {
00523 #if QT_VERSION < 0x040000
00524 const QFont font(usedFont(defaultFont));
00525 #else
00526
00527
00528
00529 const QFont font(usedFont(defaultFont), QApplication::desktop());
00530 #endif
00531
00532 if ( !d_layoutCache->textSize.isValid()
00533 || d_layoutCache->font != font )
00534 {
00535 d_layoutCache->textSize = d_data->textEngine->textSize(
00536 font, d_data->renderFlags, d_data->text);
00537 d_layoutCache->font = font;
00538 }
00539
00540 QSize sz = d_layoutCache->textSize;
00541
00542 const QwtMetricsMap map = QwtPainter::metricsMap();
00543
00544 if ( d_data->layoutAttributes & MinimumLayout )
00545 {
00546 int left, right, top, bottom;
00547 d_data->textEngine->textMargins(font, d_data->text,
00548 left, right, top, bottom);
00549 sz -= QSize(left + right, top + bottom);
00550 #if QT_VERSION >= 0x040000
00551 if ( !map.isIdentity() )
00552 {
00553 #ifdef __GNUC__
00554 #warning Too small text size, when printing in high resolution
00555 #endif
00556
00557
00558
00559
00560
00561 sz += QSize(3, 0);
00562 }
00563 #endif
00564 }
00565
00566 sz = map.screenToLayout(sz);
00567 return sz;
00568 }
00569
00576 void QwtText::draw(QPainter *painter, const QRect &rect) const
00577 {
00578 if ( d_data->paintAttributes & PaintBackground )
00579 {
00580 if ( d_data->backgroundPen != Qt::NoPen ||
00581 d_data->backgroundBrush != Qt::NoBrush )
00582 {
00583 painter->save();
00584 painter->setPen(d_data->backgroundPen);
00585 painter->setBrush(d_data->backgroundBrush);
00586 QwtPainter::drawRect(painter, rect);
00587 painter->restore();
00588 }
00589 }
00590
00591 painter->save();
00592
00593 if ( d_data->paintAttributes & PaintUsingTextFont )
00594 {
00595 painter->setFont(d_data->font);
00596 }
00597
00598 if ( d_data->paintAttributes & PaintUsingTextColor )
00599 {
00600 if ( d_data->color.isValid() )
00601 painter->setPen(d_data->color);
00602 }
00603
00604 QRect expandedRect = rect;
00605 if ( d_data->layoutAttributes & MinimumLayout )
00606 {
00607 #if QT_VERSION < 0x040000
00608 const QFont font(painter->font());
00609 #else
00610
00611
00612
00613 const QFont font(painter->font(), QApplication::desktop());
00614 #endif
00615
00616 int left, right, top, bottom;
00617 d_data->textEngine->textMargins(
00618 font, d_data->text,
00619 left, right, top, bottom);
00620
00621 const QwtMetricsMap map = QwtPainter::metricsMap();
00622 left = map.screenToLayoutX(left);
00623 right = map.screenToLayoutX(right);
00624 top = map.screenToLayoutY(top);
00625 bottom = map.screenToLayoutY(bottom);
00626
00627 expandedRect.setTop(rect.top() - top);
00628 expandedRect.setBottom(rect.bottom() + bottom);
00629 expandedRect.setLeft(rect.left() - left);
00630 expandedRect.setRight(rect.right() + right);
00631 }
00632
00633 d_data->textEngine->draw(painter, expandedRect,
00634 d_data->renderFlags, d_data->text);
00635
00636 painter->restore();
00637 }
00638
00652 const QwtTextEngine *QwtText::textEngine(const QString &text,
00653 QwtText::TextFormat format)
00654 {
00655 if ( engineDict == NULL )
00656 engineDict = new QwtTextEngineDict();
00657
00658 return engineDict->textEngine(text, format);
00659 }
00660
00672 const QwtTextEngine *QwtText::textEngine(QwtText::TextFormat format)
00673 {
00674 if ( engineDict == NULL )
00675 engineDict = new QwtTextEngineDict();
00676
00677 return engineDict->textEngine(format);
00678 }