KD Chart API Documentation 3.1
Loading...
Searching...
No Matches
KDChartTextLabelCache.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Chart library.
4**
5** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10
12
13#include <cmath>
14
15#include <QApplication>
16#include <QImage>
17#include <QPainter>
18#include <QPixmap>
19#include <QtDebug>
20
21#ifndef NDEBUG
22int HitCount = 0;
23int MissCount = 0;
24#define INC_HIT_COUNT \
25 { \
26 ++HitCount; \
27 }
28#define INC_MISS_COUNT \
29 { \
30 ++MissCount; \
31 }
32#define DUMP_CACHE_STATS \
33 if (HitCount != 0 && MissCount != 0) { \
34 int total = HitCount + MissCount; \
35 qreal hitQuote = (1.0 * HitCount) / total; \
36 qDebug() << "PrerenderedLabel dtor: hits/misses/total:" \
37 << HitCount << "/" << MissCount << "/" << total \
38 << "(" << 100 * hitQuote << "% hits)"; \
39 }
40#else
41#define INC_HIT_COUNT
42#define INC_MISS_COUNT
43#define DUMP_CACHE_STATS
44#endif
45
49
51{ // this does not invalidate the element
52 m_position = position;
53}
54
56{
57 return m_position;
58}
59
61{ // this does not invalidate the element
62 m_referencePoint = point;
63}
64
66{
67 return m_referencePoint;
68}
69
72 , m_font(qApp->font())
73 , m_brush(Qt::black)
74 , m_pen(Qt::black) // do not use anything invisible
75{
76}
77
82
87{
88 m_dirty = true;
89}
90
95{
96 m_font = font;
97 invalidate();
98}
99
104{
105 return m_font;
106}
107
112{
113 m_text = text;
114 invalidate();
115}
116
121{
122 return m_text;
123}
124
129{
130 m_brush = brush;
131 invalidate();
132}
133
138{
139 return m_brush;
140}
141
146{
147 m_angle = angle;
148 invalidate();
149}
150
155{
156 return m_angle;
157}
158
160{
161 if (m_dirty) {
163 paint();
164 } else {
166 }
167 return m_pixmap;
168}
169
170void PrerenderedLabel::paint() const
171{
172 // FIXME find a better value using font metrics of text (this
173 // requires finding the diameter of the circle formed by rotating
174 // the bounding rect around the center):
175 const int Width = 1000;
176 const int Height = Width;
177
178 QRectF boundingRect;
179 const QColor FullTransparent(255, 255, 255, 0);
180#ifdef Q_WS_X11
182 qWarning() << "PrerenderedLabel::paint: using QImage for prerendered labels "
183 << "to work around XRender/Qt4 bug.";
184#else
185 QPixmap pixmap(Width, Height);
186#endif
187 // pixmap.fill( FullTransparent );
188 {
189 static const QPointF Center(0.0, 0.0);
190 QPointF textBottomRight;
191 QPainter painter(&pixmap);
192 painter.setRenderHint(QPainter::TextAntialiasing, true);
193 painter.setRenderHint(QPainter::Antialiasing, true);
194
195 // QImage (X11 workaround) does not have fill():
196 painter.setPen(FullTransparent);
197 painter.setBrush(FullTransparent);
198 QPainter::CompositionMode mode = painter.compositionMode();
199 painter.setCompositionMode(QPainter::CompositionMode_Clear);
200 painter.drawRect(0, 0, Width, Height);
201 painter.setCompositionMode(mode);
202
203 QTransform matrix;
204 matrix.translate(0.5 * Width, 0.5 * Height);
205 matrix.rotate(m_angle);
206 painter.setWorldTransform(matrix);
207
208 painter.setPen(m_pen);
209 painter.setBrush(m_brush);
210 painter.setFont(m_font);
211 QRectF container(-0.5 * Width, -0.5 * Height, Width, 0.5 * Height);
212 painter.drawText(container, Qt::AlignHCenter | Qt::AlignBottom,
213 m_text, &boundingRect);
214 m_referenceBottomLeft = QPointF(boundingRect.bottomLeft().x(), 0.0);
215 textBottomRight = QPointF(boundingRect.bottomRight().x(), 0.0);
216 m_textAscendVector = boundingRect.topRight() - textBottomRight;
217 m_textBaseLineVector = textBottomRight - m_referenceBottomLeft;
218
219 // FIXME translate topright by char height
220 boundingRect = matrix.mapRect(boundingRect);
221 m_referenceBottomLeft = matrix.map(m_referenceBottomLeft)
222 - boundingRect.topLeft();
223 textBottomRight = matrix.map(textBottomRight)
224 - boundingRect.topLeft();
225 m_textAscendVector = matrix.map(m_textAscendVector)
226 - matrix.map(Center);
227 m_textBaseLineVector = matrix.map(m_textBaseLineVector)
228 - matrix.map(Center);
229 }
230
231 m_dirty = false; // now all the calculation vectors are valid
232
233 QPixmap temp(static_cast<int>(boundingRect.width()),
234 static_cast<int>(boundingRect.height()));
235 {
236 temp.fill(FullTransparent);
237 QPainter painter(&temp);
238#ifdef Q_WS_X11
239 painter.drawImage(QPointF(0.0, 0.0), pixmap, boundingRect);
240#else
241 painter.drawPixmap(QPointF(0.0, 0.0), pixmap, boundingRect);
242#endif
243// #define PRERENDEREDLABEL_DEBUG
244#ifdef PRERENDEREDLABEL_DEBUG
245 painter.setPen(QPen(Qt::red, 2));
246 painter.setBrush(Qt::red);
247 // paint markers for the reference points
248 const QList<KDChartEnums::PositionValue> positions = {
258 };
259 for (KDChartEnums::PositionValue position : positions) {
260 static const double Radius = 0.5;
261 static const double Diameter = 2 * Radius;
262
264 painter.drawEllipse(QRectF(point - QPointF(Radius, Radius),
265 QSizeF(Diameter, Diameter)));
266 }
267#endif
268 }
269
270 m_pixmap = temp;
271}
272
277
279{
280 if (m_dirty) {
282 paint();
283 } else {
285 }
286
287 switch (position) {
289 return m_referenceBottomLeft + 0.5 * m_textBaseLineVector + 0.5 * m_textAscendVector;
291 return m_referenceBottomLeft + m_textAscendVector;
293 return m_referenceBottomLeft + 0.5 * m_textBaseLineVector + m_textAscendVector;
295 return m_referenceBottomLeft + m_textBaseLineVector + m_textAscendVector;
297 return m_referenceBottomLeft + 0.5 * m_textAscendVector;
299 return m_referenceBottomLeft + m_textBaseLineVector;
301 return m_referenceBottomLeft + 0.5 * m_textBaseLineVector;
303 return m_referenceBottomLeft;
305 return m_referenceBottomLeft + m_textBaseLineVector + 0.5 * m_textAscendVector;
306
307 case KDChartEnums::PositionUnknown: // intentional fall-through
308 case KDChartEnums::PositionFloating: // intentional fall-through
309 return QPointF();
310 }
311
312 return QPointF();
313}
#define INC_HIT_COUNT
#define DUMP_CACHE_STATS
#define INC_MISS_COUNT
base class for prerendered elements like labels, pixmaps, markers, etc.
KDChartEnums::PositionValue referencePoint() const
void setReferencePoint(KDChartEnums::PositionValue)
void setPosition(const QPointF &position)
const QPointF & position() const
void setAngle(qreal angle)
const QString & text() const
QPointF referencePointLocation() const
void setFont(const QFont &font)
const QBrush & brush() const
void invalidate() const override
const QFont & font() const
void setBrush(const QBrush &brush)
const QPixmap & pixmap() const override
void setText(const QString &text)
Format_ARGB32_Premultiplied
qreal x() const const
QPointF bottomLeft() const const
QPointF bottomRight() const const
qreal height() const const
QPointF topLeft() const const
QPointF topRight() const const
qreal width() const const
AlignHCenter
QPoint map(const QPoint &point) const const
QRect mapRect(const QRect &rectangle) const const
QTransform & rotate(qreal angle, Qt::Axis axis)
QTransform & translate(qreal dx, qreal dy)

© 2001 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-chart/
Generated on Wed May 1 2024 00:01:10 for KD Chart API Documentation by doxygen 1.9.8