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
00215 int QwtText::operator==(const QwtText &other) const
00216 {
00217 return d_data->renderFlags == other.d_data->renderFlags &&
00218 d_data->text == other.d_data->text &&
00219 d_data->font == other.d_data->font &&
00220 d_data->color == other.d_data->color &&
00221 d_data->backgroundPen == other.d_data->backgroundPen &&
00222 d_data->backgroundBrush == other.d_data->backgroundBrush &&
00223 d_data->paintAttributes == other.d_data->paintAttributes &&
00224 d_data->textEngine == other.d_data->textEngine;
00225 }
00226
00228 int QwtText::operator!=(const QwtText &other) const
00229 {
00230 return !(other == *this);
00231 }
00232
00241 void QwtText::setText(const QString &text,
00242 QwtText::TextFormat textFormat)
00243 {
00244 d_data->text = text;
00245 d_data->textEngine = textEngine(text, textFormat);
00246 d_layoutCache->invalidate();
00247 }
00248
00253 QString QwtText::text() const
00254 {
00255 return d_data->text;
00256 }
00257
00268 void QwtText::setRenderFlags(int renderFlags)
00269 {
00270 if ( renderFlags != d_data->renderFlags )
00271 {
00272 d_data->renderFlags = renderFlags;
00273 d_layoutCache->invalidate();
00274 }
00275 }
00276
00281 int QwtText::renderFlags() const
00282 {
00283 return d_data->renderFlags;
00284 }
00285
00293 void QwtText::setFont(const QFont &font)
00294 {
00295 d_data->font = font;
00296 setPaintAttribute(PaintUsingTextFont);
00297 }
00298
00300 QFont QwtText::font() const
00301 {
00302 return d_data->font;
00303 }
00304
00312 QFont QwtText::usedFont(const QFont &defaultFont) const
00313 {
00314 if ( d_data->paintAttributes & PaintUsingTextFont )
00315 return d_data->font;
00316
00317 return defaultFont;
00318 }
00319
00327 void QwtText::setColor(const QColor &color)
00328 {
00329 d_data->color = color;
00330 setPaintAttribute(PaintUsingTextColor);
00331 }
00332
00334 QColor QwtText::color() const
00335 {
00336 return d_data->color;
00337 }
00338
00346 QColor QwtText::usedColor(const QColor &defaultColor) const
00347 {
00348 if ( d_data->paintAttributes & PaintUsingTextColor )
00349 return d_data->color;
00350
00351 return defaultColor;
00352 }
00353
00360 void QwtText::setBackgroundPen(const QPen &pen)
00361 {
00362 d_data->backgroundPen = pen;
00363 setPaintAttribute(PaintBackground);
00364 }
00365
00370 QPen QwtText::backgroundPen() const
00371 {
00372 return d_data->backgroundPen;
00373 }
00374
00381 void QwtText::setBackgroundBrush(const QBrush &brush)
00382 {
00383 d_data->backgroundBrush = brush;
00384 setPaintAttribute(PaintBackground);
00385 }
00386
00391 QBrush QwtText::backgroundBrush() const
00392 {
00393 return d_data->backgroundBrush;
00394 }
00395
00406 void QwtText::setPaintAttribute(PaintAttribute attribute, bool on)
00407 {
00408 if ( on )
00409 d_data->paintAttributes |= attribute;
00410 else
00411 d_data->paintAttributes &= ~attribute;
00412 }
00413
00422 bool QwtText::testPaintAttribute(PaintAttribute attribute) const
00423 {
00424 return d_data->paintAttributes & attribute;
00425 }
00426
00434 void QwtText::setLayoutAttribute(LayoutAttribute attribute, bool on)
00435 {
00436 if ( on )
00437 d_data->layoutAttributes |= attribute;
00438 else
00439 d_data->layoutAttributes &= ~attribute;
00440 }
00441
00450 bool QwtText::testLayoutAttribute(LayoutAttribute attribute) const
00451 {
00452 return d_data->layoutAttributes | attribute;
00453 }
00454
00463 int QwtText::heightForWidth(int width, const QFont &defaultFont) const
00464 {
00465 const QwtMetricsMap map = QwtPainter::metricsMap();
00466 width = map.layoutToScreenX(width);
00467
00468 #if QT_VERSION < 0x040000
00469 const QFont font = usedFont(defaultFont);
00470 #else
00471
00472
00473
00474 const QFont font(usedFont(defaultFont), QApplication::desktop());
00475 #endif
00476
00477 int h = 0;
00478
00479 if ( d_data->layoutAttributes & MinimumLayout )
00480 {
00481 int left, right, top, bottom;
00482 d_data->textEngine->textMargins(font, d_data->text,
00483 left, right, top, bottom);
00484
00485 h = d_data->textEngine->heightForWidth(
00486 font, d_data->renderFlags, d_data->text,
00487 width + left + right);
00488
00489 h -= top + bottom;
00490 }
00491 else
00492 {
00493 h = d_data->textEngine->heightForWidth(
00494 font, d_data->renderFlags, d_data->text, width);
00495 }
00496
00497 h = map.screenToLayoutY(h);
00498 return h;
00499 }
00500
00515 QSize QwtText::textSize(const QFont &defaultFont) const
00516 {
00517 #if QT_VERSION < 0x040000
00518 const QFont font(usedFont(defaultFont));
00519 #else
00520
00521
00522
00523 const QFont font(usedFont(defaultFont), QApplication::desktop());
00524 #endif
00525
00526 if ( !d_layoutCache->textSize.isValid()
00527 || d_layoutCache->font != font )
00528 {
00529 d_layoutCache->textSize = d_data->textEngine->textSize(
00530 font, d_data->renderFlags, d_data->text);
00531 d_layoutCache->font = font;
00532 }
00533
00534 QSize sz = d_layoutCache->textSize;
00535
00536 const QwtMetricsMap map = QwtPainter::metricsMap();
00537
00538 if ( d_data->layoutAttributes & MinimumLayout )
00539 {
00540 int left, right, top, bottom;
00541 d_data->textEngine->textMargins(font, d_data->text,
00542 left, right, top, bottom);
00543 sz -= QSize(left + right, top + bottom);
00544
00545 #if QT_VERSION >= 0x040000
00546 if ( !map.isIdentity() )
00547 {
00548 #ifdef __GNUC__
00549 #endif
00550
00551
00552
00553
00554
00555 sz += QSize(3, 2);
00556 }
00557 #endif
00558 }
00559
00560 sz = map.screenToLayout(sz);
00561 return sz;
00562 }
00563
00570 void QwtText::draw(QPainter *painter, const QRect &rect) const
00571 {
00572 if ( d_data->paintAttributes & PaintBackground )
00573 {
00574 if ( d_data->backgroundPen != Qt::NoPen ||
00575 d_data->backgroundBrush != Qt::NoBrush )
00576 {
00577 painter->save();
00578 painter->setPen(QwtPainter::scaledPen(d_data->backgroundPen));
00579 painter->setBrush(d_data->backgroundBrush);
00580 #if QT_VERSION < 0x040000
00581 QwtPainter::drawRect(painter, rect);
00582 #else
00583 const QRect r(rect.x(), rect.y(),
00584 rect.width() - 1, rect.height() - 1);
00585 QwtPainter::drawRect(painter, r);
00586 #endif
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 {
00657
00658
00659
00660
00661
00662
00663 engineDict = new QwtTextEngineDict();
00664 }
00665
00666 return engineDict->textEngine(text, format);
00667 }
00668
00687 void QwtText::setTextEngine(QwtText::TextFormat format,
00688 QwtTextEngine *engine)
00689 {
00690 if ( engineDict == NULL )
00691 engineDict = new QwtTextEngineDict();
00692
00693 engineDict->setTextEngine(format, engine);
00694 }
00695
00707 const QwtTextEngine *QwtText::textEngine(QwtText::TextFormat format)
00708 {
00709 if ( engineDict == NULL )
00710 engineDict = new QwtTextEngineDict();
00711
00712 return engineDict->textEngine(format);
00713 }