1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2003 Uwe Rathmann
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the Qwt License, Version 1.0
8
*****************************************************************************/
18
#include "qwt_painter.h"
19
#include "qwt_text_engine.h"
21
#if QT_VERSION >= 0x040000
22
#include <qapplication.h>
23
#include <qdesktopwidget.h>
26
class QwtTextEngineDict
32
void setTextEngine(QwtText::TextFormat, QwtTextEngine *);
33
const QwtTextEngine *textEngine(QwtText::TextFormat) const;
34
const QwtTextEngine *textEngine(const QString &,
35
QwtText::TextFormat) const;
38
typedef QMap<int, QwtTextEngine *> EngineMap;
40
inline const QwtTextEngine *engine(EngineMap::const_iterator &it) const
42
#if QT_VERSION < 0x040000
52
QwtTextEngineDict::QwtTextEngineDict()
54
d_map.insert(QwtText::PlainText, new QwtPlainTextEngine());
55
#ifndef QT_NO_RICHTEXT
56
d_map.insert(QwtText::RichText, new QwtRichTextEngine());
60
QwtTextEngineDict::~QwtTextEngineDict()
62
for ( EngineMap::const_iterator it = d_map.begin();
63
it != d_map.end(); ++it )
65
QwtTextEngine *textEngine = (QwtTextEngine *)engine(it);
70
const QwtTextEngine *QwtTextEngineDict::textEngine(const QString& text,
71
QwtText::TextFormat format) const
73
if ( format == QwtText::AutoText )
75
for ( EngineMap::const_iterator it = d_map.begin();
76
it != d_map.end(); ++it )
78
if ( it.key() != QwtText::PlainText )
80
const QwtTextEngine *e = engine(it);
81
if ( e && e->mightRender(text) )
82
return (QwtTextEngine *)e;
87
EngineMap::const_iterator it = d_map.find(format);
88
if ( it != d_map.end() )
90
const QwtTextEngine *e = engine(it);
95
it = d_map.find(QwtText::PlainText);
99
void QwtTextEngineDict::setTextEngine(QwtText::TextFormat format,
100
QwtTextEngine *engine)
102
if ( format == QwtText::AutoText )
105
if ( format == QwtText::PlainText && engine == NULL )
108
EngineMap::const_iterator it = d_map.find(format);
109
if ( it != d_map.end() )
111
const QwtTextEngine *e = this->engine(it);
115
d_map.remove(format);
118
if ( engine != NULL )
119
d_map.insert(format, engine);
122
const QwtTextEngine *QwtTextEngineDict::textEngine(
123
QwtText::TextFormat format) const
125
const QwtTextEngine *e = NULL;
127
EngineMap::const_iterator it = d_map.find(format);
128
if ( it != d_map.end() )
134
static QwtTextEngineDict *engineDict = NULL;
136
class QwtText::PrivateData
140
renderFlags(Qt::AlignCenter),
141
backgroundPen(Qt::NoPen),
142
backgroundBrush(Qt::NoBrush),
154
QBrush backgroundBrush;
157
int layoutAttributes;
159
const QwtTextEngine *textEngine;
162
class QwtText::LayoutCache
177
\param text Text content
178
\param textFormat Text format
180
QwtText::QwtText(const QString &text, QwtText::TextFormat textFormat)
182
d_data = new PrivateData;
184
d_data->textEngine = textEngine(text, textFormat);
186
d_layoutCache = new LayoutCache;
190
QwtText::QwtText(const QwtText &other)
192
d_data = new PrivateData;
193
*d_data = *other.d_data;
195
d_layoutCache = new LayoutCache;
196
*d_layoutCache = *other.d_layoutCache;
203
delete d_layoutCache;
206
//! Assignement operator
207
QwtText &QwtText::operator=(const QwtText &other)
209
*d_data = *other.d_data;
210
*d_layoutCache = *other.d_layoutCache;
214
int QwtText::operator==(const QwtText &other) const
216
return d_data->renderFlags == other.d_data->renderFlags &&
217
d_data->text == other.d_data->text &&
218
d_data->font == other.d_data->font &&
219
d_data->color == other.d_data->color &&
220
d_data->backgroundPen == other.d_data->backgroundPen &&
221
d_data->backgroundBrush == other.d_data->backgroundBrush &&
222
d_data->paintAttributes == other.d_data->paintAttributes &&
223
d_data->textEngine == other.d_data->textEngine;
226
int QwtText::operator!=(const QwtText &other) const // invalidate
228
return !(other == *this);
232
Assign a new text content
234
\param text Text content
235
\param textFormat Text format
237
void QwtText::setText(const QString &text,
238
QwtText::TextFormat textFormat)
241
d_data->textEngine = textEngine(text, textFormat);
242
d_layoutCache->invalidate();
249
QString QwtText::text() const
255
\brief Change the render flags
257
The default setting is Qt::AlignCenter
259
\param renderFlags Bitwise OR of the flags used like in QPainter::drawText
261
\sa renderFlags, QwtTextEngine::draw
262
\note Some renderFlags might have no effect, depending on the text format.
264
void QwtText::setRenderFlags(int renderFlags)
266
if ( renderFlags != d_data->renderFlags )
268
d_data->renderFlags = renderFlags;
269
d_layoutCache->invalidate();
277
int QwtText::renderFlags() const
279
return d_data->renderFlags;
286
\note Setting the font might have no effect, when
287
the text contains control sequences for setting fonts.
289
void QwtText::setFont(const QFont &font)
292
setPaintAttribute(PaintUsingTextFont);
296
QFont QwtText::font() const
302
Return the font of the text, if it has one.
303
Otherwise return defaultFont.
305
\param defaultFont Default font
306
\sa setFont, font, PaintAttributes
308
QFont QwtText::usedFont(const QFont &defaultFont) const
310
if ( d_data->paintAttributes & PaintUsingTextFont )
317
Set the pen color used for painting the text.
320
\note Setting the color might have no effect, when
321
the text contains control sequences for setting colors.
323
void QwtText::setColor(const QColor &color)
325
d_data->color = color;
326
setPaintAttribute(PaintUsingTextColor);
329
//! Return the pen color, used for painting the text
330
QColor QwtText::color() const
332
return d_data->color;
336
Return the color of the text, if it has one.
337
Otherwise return defaultColor.
339
\param defaultColor Default color
340
\sa setColor, color, PaintAttributes
342
QColor QwtText::usedColor(const QColor &defaultColor) const
344
if ( d_data->paintAttributes & PaintUsingTextColor )
345
return d_data->color;
351
Set the background pen
353
\param pen Background pen
354
\sa backgroundPen, setBackgroundBrush
356
void QwtText::setBackgroundPen(const QPen &pen)
358
d_data->backgroundPen = pen;
359
setPaintAttribute(PaintBackground);
363
\return Background pen
364
\sa setBackgroundPen, backgroundBrush
366
QPen QwtText::backgroundPen() const
368
return d_data->backgroundPen;
372
Set the background brush
374
\param brush Background brush
375
\sa backgroundBrush, setBackgroundPen
377
void QwtText::setBackgroundBrush(const QBrush &brush)
379
d_data->backgroundBrush = brush;
380
setPaintAttribute(PaintBackground);
384
\return Background brush
385
\sa setBackgroundBrush, backgroundPen
387
QBrush QwtText::backgroundBrush() const
389
return d_data->backgroundBrush;
393
Change a paint attribute
395
\param attribute Paint attribute
398
\note Used by setFont, setColor, setBackgroundPen and setBackgroundBrush
399
\sa testPaintAttribute
401
void QwtText::setPaintAttribute(PaintAttribute attribute, bool on)
404
d_data->paintAttributes |= attribute;
406
d_data->paintAttributes &= ~attribute;
410
Test a paint attribute
412
\param attribute Paint attribute
413
\return true, if attribute is enabled
415
\sa setPaintAttribute
417
bool QwtText::testPaintAttribute(PaintAttribute attribute) const
419
return d_data->paintAttributes & attribute;
423
Change a layout attribute
425
\param attribute Layout attribute
427
\sa testLayoutAttribute
429
void QwtText::setLayoutAttribute(LayoutAttribute attribute, bool on)
432
d_data->layoutAttributes |= attribute;
434
d_data->layoutAttributes &= ~attribute;
438
Test a layout attribute
440
\param attribute Layout attribute
441
\return true, if attribute is enabled
443
\sa setLayoutAttribute
445
bool QwtText::testLayoutAttribute(LayoutAttribute attribute) const
447
return d_data->layoutAttributes | attribute;
451
Find the height for a given width
453
\param defaultFont Font, used for the calculation if the text has no font
456
\return Calculated height
458
int QwtText::heightForWidth(int width, const QFont &defaultFont) const
460
const QwtMetricsMap map = QwtPainter::metricsMap();
461
width = map.layoutToScreenX(width);
463
#if QT_VERSION < 0x040000
464
const QFont font = usedFont(defaultFont);
466
// We want to calculate in screen metrics. So
467
// we need a font that uses screen metrics
469
const QFont font(usedFont(defaultFont), QApplication::desktop());
474
if ( d_data->layoutAttributes & MinimumLayout )
476
int left, right, top, bottom;
477
d_data->textEngine->textMargins(font, d_data->text,
478
left, right, top, bottom);
480
h = d_data->textEngine->heightForWidth(
481
font, d_data->renderFlags, d_data->text,
482
width + left + right);
488
h = d_data->textEngine->heightForWidth(
489
font, d_data->renderFlags, d_data->text, width);
492
h = map.screenToLayoutY(h);
497
Find the height for a given width
499
\param defaultFont Font, used for the calculation if the text has no font
501
\return Calculated height
505
Returns the size, that is needed to render text
507
\param defaultFont Font of the text
508
\return Caluclated size
510
QSize QwtText::textSize(const QFont &defaultFont) const
512
#if QT_VERSION < 0x040000
513
const QFont font(usedFont(defaultFont));
515
// We want to calculate in screen metrics. So
516
// we need a font that uses screen metrics
518
const QFont font(usedFont(defaultFont), QApplication::desktop());
521
if ( !d_layoutCache->textSize.isValid()
522
|| d_layoutCache->font != font )
524
d_layoutCache->textSize = d_data->textEngine->textSize(
525
font, d_data->renderFlags, d_data->text);
526
d_layoutCache->font = font;
529
QSize sz = d_layoutCache->textSize;
531
const QwtMetricsMap map = QwtPainter::metricsMap();
533
if ( d_data->layoutAttributes & MinimumLayout )
535
int left, right, top, bottom;
536
d_data->textEngine->textMargins(font, d_data->text,
537
left, right, top, bottom);
538
sz -= QSize(left + right, top + bottom);
539
#if QT_VERSION >= 0x040000
540
if ( !map.isIdentity() )
545
When printing in high resolution, the tick labels
546
of are cut of. We need to find out why, but for
547
the moment we add a couple of pixels instead.
554
sz = map.screenToLayout(sz);
559
Draw a text into a rectangle
561
\param painter Painter
562
\param rect Rectangle
564
void QwtText::draw(QPainter *painter, const QRect &rect) const
566
if ( d_data->paintAttributes & PaintBackground )
568
if ( d_data->backgroundPen != Qt::NoPen ||
569
d_data->backgroundBrush != Qt::NoBrush )
572
painter->setPen(d_data->backgroundPen);
573
painter->setBrush(d_data->backgroundBrush);
574
#if QT_VERSION < 0x040000
575
QwtPainter::drawRect(painter, rect);
577
const QRect r(rect.x(), rect.y(),
578
rect.width() - 1, rect.height() - 1);
579
QwtPainter::drawRect(painter, r);
587
if ( d_data->paintAttributes & PaintUsingTextFont )
589
painter->setFont(d_data->font);
592
if ( d_data->paintAttributes & PaintUsingTextColor )
594
if ( d_data->color.isValid() )
595
painter->setPen(d_data->color);
598
QRect expandedRect = rect;
599
if ( d_data->layoutAttributes & MinimumLayout )
601
#if QT_VERSION < 0x040000
602
const QFont font(painter->font());
604
// We want to calculate in screen metrics. So
605
// we need a font that uses screen metrics
607
const QFont font(painter->font(), QApplication::desktop());
610
int left, right, top, bottom;
611
d_data->textEngine->textMargins(
613
left, right, top, bottom);
615
const QwtMetricsMap map = QwtPainter::metricsMap();
616
left = map.screenToLayoutX(left);
617
right = map.screenToLayoutX(right);
618
top = map.screenToLayoutY(top);
619
bottom = map.screenToLayoutY(bottom);
621
expandedRect.setTop(rect.top() - top);
622
expandedRect.setBottom(rect.bottom() + bottom);
623
expandedRect.setLeft(rect.left() - left);
624
expandedRect.setRight(rect.right() + right);
627
d_data->textEngine->draw(painter, expandedRect,
628
d_data->renderFlags, d_data->text);
634
Find the text engine for a text format
636
In case of QwtText::AutoText the first text engine
637
(beside QwtPlainTextEngine) is returned, where QwtTextEngine::mightRender
638
returns true. If there is none QwtPlainTextEngine is returnd.
640
If no text engine is registered for the format QwtPlainTextEngine
643
\param text Text, needed in case of AutoText
644
\param format Text format
646
const QwtTextEngine *QwtText::textEngine(const QString &text,
647
QwtText::TextFormat format)
649
if ( engineDict == NULL )
652
Note: engineDict is allocated, the first time it is used,
653
but never deleted, because there is no known last access time.
654
So don't be irritated, if it is reported as a memory leak
655
from your memory profiler.
657
engineDict = new QwtTextEngineDict();
660
return engineDict->textEngine(text, format);
664
Assign/Replace a text engine for a text format
666
With setTextEngine it is possible to extend Qwt with
667
other types of text formats.
669
Owner of a commercial Qt license can build the qwtmathml library,
670
that is based on the MathML renderer, that is included in MML Widget
671
component of the Qt solutions package.
673
For QwtText::PlainText it is not allowed to assign a engine == NULL.
675
\param format Text format
676
\param engine Text engine
678
\sa QwtMathMLTextEngine
679
\warning Using QwtText::AutoText does nothing.
681
void QwtText::setTextEngine(QwtText::TextFormat format,
682
QwtTextEngine *engine)
684
if ( engineDict == NULL )
685
engineDict = new QwtTextEngineDict();
687
engineDict->setTextEngine(format, engine);
691
\brief Find the text engine for a text format
693
textEngine can be used to find out if a text format is supported.
694
F.e, if one wants to use MathML labels, the MathML renderer from the
695
commercial Qt solutions package might be required, that is not
696
available in Qt Open Source Edition environments.
698
\param format Text format
699
\return The text engine, or NULL if no engine is available.
701
const QwtTextEngine *QwtText::textEngine(QwtText::TextFormat format)
703
if ( engineDict == NULL )
704
engineDict = new QwtTextEngineDict();
706
return engineDict->textEngine(format);