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 <qapplication.h>
00023 #include <qdesktopwidget.h>
00024 #endif
00025
00026 class QwtTextEngineDict
00027 {
00028 public:
00029 QwtTextEngineDict();
00030 ~QwtTextEngineDict();
00031
00032 void setTextEngine(QwtText::TextFormat, QwtTextEngine *);
00033 const QwtTextEngine *textEngine(QwtText::TextFormat) const;
00034 const QwtTextEngine *textEngine(const QString &,
00035 QwtText::TextFormat) const;
00036
00037 private:
00038 typedef QMap<int, QwtTextEngine *> EngineMap;
00039
00040 inline const QwtTextEngine *engine(EngineMap::const_iterator &it) const
00041 {
00042 #if QT_VERSION < 0x040000
00043 return it.data();
00044 #else
00045 return it.value();
00046 #endif
00047 }
00048
00049 EngineMap d_map;
00050 };
00051
00052 QwtTextEngineDict::QwtTextEngineDict()
00053 {
00054 d_map.insert(QwtText::PlainText, new QwtPlainTextEngine());
00055 #ifndef QT_NO_RICHTEXT
00056 d_map.insert(QwtText::RichText, new QwtRichTextEngine());
00057 #endif
00058 }
00059
00060 QwtTextEngineDict::~QwtTextEngineDict()
00061 {
00062 for ( EngineMap::const_iterator it = d_map.begin();
00063 it != d_map.end(); ++it )
00064 {
00065 QwtTextEngine *textEngine = (QwtTextEngine *)engine(it);
00066 delete textEngine;
00067 }
00068 }
00069
00070 const QwtTextEngine *QwtTextEngineDict::textEngine(const QString& text,
00071 QwtText::TextFormat format) const
00072 {
00073 if ( format == QwtText::AutoText )
00074 {
00075 for ( EngineMap::const_iterator it = d_map.begin();
00076 it != d_map.end(); ++it )
00077 {
00078 if ( it.key() != QwtText::PlainText )
00079 {
00080 const QwtTextEngine *e = engine(it);
00081 if ( e && e->mightRender(text) )
00082 return (QwtTextEngine *)e;
00083 }
00084 }
00085 }
00086
00087 EngineMap::const_iterator it = d_map.find(format);
00088 if ( it != d_map.end() )
00089 {
00090 const QwtTextEngine *e = engine(it);
00091 if ( e )
00092 return e;
00093 }
00094
00095 it = d_map.find(QwtText::PlainText);
00096 return engine(it);
00097 }
00098
00099 void QwtTextEngineDict::setTextEngine(QwtText::TextFormat format,
00100 QwtTextEngine *engine)
00101 {
00102 if ( format == QwtText::AutoText )
00103 return;
00104
00105 if ( format == QwtText::PlainText && engine == NULL )
00106 return;
00107
00108 EngineMap::const_iterator it = d_map.find(format);
00109 if ( it != d_map.end() )
00110 {
00111 const QwtTextEngine *e = this->engine(it);
00112 if ( e )
00113 delete e;
00114
00115 d_map.remove(format);
00116 }
00117
00118 if ( engine != NULL )
00119 d_map.insert(format, engine);
00120 }
00121
00122 const QwtTextEngine *QwtTextEngineDict::textEngine(
00123 QwtText::TextFormat format) const
00124 {
00125 const QwtTextEngine *e = NULL;
00126
00127 EngineMap::const_iterator it = d_map.find(format);
00128 if ( it != d_map.end() )
00129 e = engine(it);
00130
00131 return e;
00132 }
00133
00134 static QwtTextEngineDict *engineDict = NULL;
00135
00136 class QwtText::PrivateData
00137 {
00138 public:
00139 PrivateData():
00140 renderFlags(Qt::AlignCenter),
00141 backgroundPen(Qt::NoPen),
00142 backgroundBrush(Qt::NoBrush),
00143 paintAttributes(0),
00144 layoutAttributes(0),
00145 textEngine(NULL)
00146 {
00147 }
00148
00149 int renderFlags;
00150 QString text;
00151 QFont font;
00152 QColor color;
00153 QPen backgroundPen;
00154 QBrush backgroundBrush;
00155
00156 int paintAttributes;
00157 int layoutAttributes;
00158
00159 const QwtTextEngine *textEngine;
00160 };
00161
00162 class QwtText::LayoutCache
00163 {
00164 public:
00165 void invalidate()
00166 {
00167 textSize = QSize();
00168 }
00169
00170 QFont font;
00171 QSize textSize;
00172 };
00173
00180 QwtText::QwtText(const QString &text, QwtText::TextFormat textFormat)
00181 {
00182 d_data = new PrivateData;
00183 d_data->text = text;
00184 d_data->textEngine = textEngine(text, textFormat);
00185
00186 d_layoutCache = new LayoutCache;
00187 }
00188
00190 QwtText::QwtText(const QwtText &other)
00191 {
00192 d_data = new PrivateData;
00193 *d_data = *other.d_data;
00194
00195 d_layoutCache = new LayoutCache;
00196 *d_layoutCache = *other.d_layoutCache;
00197 }
00198
00200 QwtText::~QwtText()
00201 {
00202 delete d_data;
00203 delete d_layoutCache;
00204 }
00205
00207 QwtText &QwtText::operator=(const QwtText &other)
00208 {
00209 *d_data = *other.d_data;
00210 *d_layoutCache = *other.d_layoutCache;
00211 return *this;
00212 }
00213
00214 int QwtText::operator==(const QwtText &other) const
00215 {
00216 return d_data->renderFlags == other.d_data->renderFlags &&
00217 d_data->text == other.d_data->text &&
00218 d_data->font == other.d_data->font &&
00219 d_data->color == other.d_data->color &&
00220 d_data->backgroundPen == other.d_data->backgroundPen &&
00221 d_data->backgroundBrush == other.d_data->backgroundBrush &&
00222 d_data->paintAttributes == other.d_data->paintAttributes &&
00223 d_data->textEngine == other.d_data->textEngine;
00224 }
00225
00226 int QwtText::operator!=(const QwtText &other) const
00227 {
00228 return !(other == *this);
00229 }
00230
00237 void QwtText::setText(const QString &text,
00238 QwtText::TextFormat textFormat)
00239 {
00240 d_data->text = text;
00241 d_data->textEngine = textEngine(text, textFormat);
00242 d_layoutCache->invalidate();
00243 }
00244
00249 QString QwtText::text() const
00250 {
00251 return d_data->text;
00252 }
00253
00264 void QwtText::setRenderFlags(int renderFlags)
00265 {
00266 if ( renderFlags != d_data->renderFlags )
00267 {
00268 d_data->renderFlags = renderFlags;
00269 d_layoutCache->invalidate();
00270 }
00271 }
00272
00277 int QwtText::renderFlags() const
00278 {
00279 return d_data->renderFlags;
00280 }
00281
00289 void QwtText::setFont(const QFont &font)
00290 {
00291 d_data->font = font;
00292 setPaintAttribute(PaintUsingTextFont);
00293 }
00294
00296 QFont QwtText::font() const
00297 {
00298 return d_data->font;
00299 }
00300
00308 QFont QwtText::usedFont(const QFont &defaultFont) const
00309 {
00310 if ( d_data->paintAttributes & PaintUsingTextFont )
00311 return d_data->font;
00312
00313 return defaultFont;
00314 }
00315
00323 void QwtText::setColor(const QColor &color)
00324 {
00325 d_data->color = color;
00326 setPaintAttribute(PaintUsingTextColor);
00327 }
00328
00330 QColor QwtText::color() const
00331 {
00332 return d_data->color;
00333 }
00334
00342 QColor QwtText::usedColor(const QColor &defaultColor) const
00343 {
00344 if ( d_data->paintAttributes & PaintUsingTextColor )
00345 return d_data->color;
00346
00347 return defaultColor;
00348 }
00349
00356 void QwtText::setBackgroundPen(const QPen &pen)
00357 {
00358 d_data->backgroundPen = pen;
00359 setPaintAttribute(PaintBackground);
00360 }
00361
00366 QPen QwtText::backgroundPen() const
00367 {
00368 return d_data->backgroundPen;
00369 }
00370
00377 void QwtText::setBackgroundBrush(const QBrush &brush)
00378 {
00379 d_data->backgroundBrush = brush;
00380 setPaintAttribute(PaintBackground);
00381 }
00382
00387 QBrush QwtText::backgroundBrush() const
00388 {
00389 return d_data->backgroundBrush;
00390 }
00391
00401 void QwtText::setPaintAttribute(PaintAttribute attribute, bool on)
00402 {
00403 if ( on )
00404 d_data->paintAttributes |= attribute;
00405 else
00406 d_data->paintAttributes &= ~attribute;
00407 }
00408
00417 bool QwtText::testPaintAttribute(PaintAttribute attribute) const
00418 {
00419 return d_data->paintAttributes & attribute;
00420 }
00421
00429 void QwtText::setLayoutAttribute(LayoutAttribute attribute, bool on)
00430 {
00431 if ( on )
00432 d_data->layoutAttributes |= attribute;
00433 else
00434 d_data->layoutAttributes &= ~attribute;
00435 }
00436
00445 bool QwtText::testLayoutAttribute(LayoutAttribute attribute) const
00446 {
00447 return d_data->layoutAttributes | attribute;
00448 }
00449
00458 int QwtText::heightForWidth(int width, const QFont &defaultFont) const
00459 {
00460 const QwtMetricsMap map = QwtPainter::metricsMap();
00461 width = map.layoutToScreenX(width);
00462
00463 #if QT_VERSION < 0x040000
00464 const QFont font = usedFont(defaultFont);
00465 #else
00466
00467
00468
00469 const QFont font(usedFont(defaultFont), QApplication::desktop());
00470 #endif
00471
00472 int h = 0;
00473
00474 if ( d_data->layoutAttributes & MinimumLayout )
00475 {
00476 int left, right, top, bottom;
00477 d_data->textEngine->textMargins(font, d_data->text,
00478 left, right, top, bottom);
00479
00480 h = d_data->textEngine->heightForWidth(
00481 font, d_data->renderFlags, d_data->text,
00482 width + left + right);
00483
00484 h -= top + bottom;
00485 }
00486 else
00487 {
00488 h = d_data->textEngine->heightForWidth(
00489 font, d_data->renderFlags, d_data->text, width);
00490 }
00491
00492 h = map.screenToLayoutY(h);
00493 return h;
00494 }
00495
00510 QSize QwtText::textSize(const QFont &defaultFont) const
00511 {
00512 #if QT_VERSION < 0x040000
00513 const QFont font(usedFont(defaultFont));
00514 #else
00515
00516
00517
00518 const QFont font(usedFont(defaultFont), QApplication::desktop());
00519 #endif
00520
00521 if ( !d_layoutCache->textSize.isValid()
00522 || d_layoutCache->font != font )
00523 {
00524 d_layoutCache->textSize = d_data->textEngine->textSize(
00525 font, d_data->renderFlags, d_data->text);
00526 d_layoutCache->font = font;
00527 }
00528
00529 QSize sz = d_layoutCache->textSize;
00530
00531 const QwtMetricsMap map = QwtPainter::metricsMap();
00532
00533 if ( d_data->layoutAttributes & MinimumLayout )
00534 {
00535 int left, right, top, bottom;
00536 d_data->textEngine->textMargins(font, d_data->text,
00537 left, right, top, bottom);
00538 sz -= QSize(left + right, top + bottom);
00539 #if QT_VERSION >= 0x040000
00540 if ( !map.isIdentity() )
00541 {
00542 #ifdef __GNUC__
00543 #endif
00544
00545
00546
00547
00548
00549 sz += QSize(3, 0);
00550 }
00551 #endif
00552 }
00553
00554 sz = map.screenToLayout(sz);
00555 return sz;
00556 }
00557
00564 void QwtText::draw(QPainter *painter, const QRect &rect) const
00565 {
00566 if ( d_data->paintAttributes & PaintBackground )
00567 {
00568 if ( d_data->backgroundPen != Qt::NoPen ||
00569 d_data->backgroundBrush != Qt::NoBrush )
00570 {
00571 painter->save();
00572 painter->setPen(d_data->backgroundPen);
00573 painter->setBrush(d_data->backgroundBrush);
00574 QwtPainter::drawRect(painter, rect);
00575 painter->restore();
00576 }
00577 }
00578
00579 painter->save();
00580
00581 if ( d_data->paintAttributes & PaintUsingTextFont )
00582 {
00583 painter->setFont(d_data->font);
00584 }
00585
00586 if ( d_data->paintAttributes & PaintUsingTextColor )
00587 {
00588 if ( d_data->color.isValid() )
00589 painter->setPen(d_data->color);
00590 }
00591
00592 QRect expandedRect = rect;
00593 if ( d_data->layoutAttributes & MinimumLayout )
00594 {
00595 #if QT_VERSION < 0x040000
00596 const QFont font(painter->font());
00597 #else
00598
00599
00600
00601 const QFont font(painter->font(), QApplication::desktop());
00602 #endif
00603
00604 int left, right, top, bottom;
00605 d_data->textEngine->textMargins(
00606 font, d_data->text,
00607 left, right, top, bottom);
00608
00609 const QwtMetricsMap map = QwtPainter::metricsMap();
00610 left = map.screenToLayoutX(left);
00611 right = map.screenToLayoutX(right);
00612 top = map.screenToLayoutY(top);
00613 bottom = map.screenToLayoutY(bottom);
00614
00615 expandedRect.setTop(rect.top() - top);
00616 expandedRect.setBottom(rect.bottom() + bottom);
00617 expandedRect.setLeft(rect.left() - left);
00618 expandedRect.setRight(rect.right() + right);
00619 }
00620
00621 d_data->textEngine->draw(painter, expandedRect,
00622 d_data->renderFlags, d_data->text);
00623
00624 painter->restore();
00625 }
00626
00640 const QwtTextEngine *QwtText::textEngine(const QString &text,
00641 QwtText::TextFormat format)
00642 {
00643 if ( engineDict == NULL )
00644 engineDict = new QwtTextEngineDict();
00645
00646 return engineDict->textEngine(text, format);
00647 }
00648
00667 void QwtText::setTextEngine(QwtText::TextFormat format,
00668 QwtTextEngine *engine)
00669 {
00670 if ( engineDict == NULL )
00671 engineDict = new QwtTextEngineDict();
00672
00673 engineDict->setTextEngine(format, engine);
00674 }
00675
00687 const QwtTextEngine *QwtText::textEngine(QwtText::TextFormat format)
00688 {
00689 if ( engineDict == NULL )
00690 engineDict = new QwtTextEngineDict();
00691
00692 return engineDict->textEngine(format);
00693 }