1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
5
6#include "axisrendercache_p.h"
7
8#include <QtGui/QFontMetrics>
9
10QT_BEGIN_NAMESPACE
11
12AxisRenderCache::AxisRenderCache()
13 : m_type(QAbstract3DAxis::AxisTypeNone),
14 m_min(0.0f),
15 m_max(10.0f),
16 m_segmentCount(5),
17 m_subSegmentCount(1),
18 m_reversed(false),
19 m_font(QFont(QStringLiteral("Arial"))),
20 m_formatter(0),
21 m_ctrlFormatter(0),
22 m_drawer(0),
23 m_positionsDirty(true),
24 m_translate(0.0f),
25 m_scale(1.0f),
26 m_labelAutoRotation(0.0f),
27 m_titleVisible(false),
28 m_titleFixed(false)
29{
30}
31
32AxisRenderCache::~AxisRenderCache()
33{
34 foreach (LabelItem *label, m_labelItems)
35 delete label;
36 m_titleItem.clear();
37
38 delete m_formatter;
39}
40
41void AxisRenderCache::setDrawer(Drawer *drawer)
42{
43 m_drawer = drawer;
44 m_font = m_drawer->font();
45 if (m_drawer)
46 updateTextures();
47}
48
49void AxisRenderCache::setType(QAbstract3DAxis::AxisType type)
50{
51 m_type = type;
52
53 // If type is set, it means completely new axis instance, so clear all old data
54 m_labels.clear();
55 m_title.clear();
56 m_min = 0.0f;
57 m_max = 10.0f;
58 m_segmentCount = 5;
59 m_subSegmentCount = 1;
60 m_labelFormat.clear();
61
62 m_titleItem.clear();
63 foreach (LabelItem *label, m_labelItems)
64 delete label;
65 m_labelItems.clear();
66}
67
68void AxisRenderCache::setTitle(const QString &title)
69{
70 if (m_title != title) {
71 m_title = title;
72 // Generate axis label texture
73 if (m_drawer)
74 m_drawer->generateLabelItem(item&: m_titleItem, text: title);
75 }
76}
77
78void AxisRenderCache::setLabels(const QStringList &labels)
79{
80 if (m_labels != labels) {
81 int newSize(labels.size());
82 int oldSize(m_labels.size());
83
84 for (int i = newSize; i < oldSize; i++)
85 delete m_labelItems.takeLast();
86
87 m_labelItems.reserve(asize: newSize);
88
89 int widest = maxLabelWidth(labels);
90
91 for (int i = 0; i < newSize; i++) {
92 if (i >= oldSize)
93 m_labelItems.append(t: new LabelItem);
94 if (m_drawer) {
95 if (labels.at(i).isEmpty()) {
96 m_labelItems[i]->clear();
97 } else if (i >= oldSize || labels.at(i) != m_labels.at(i)
98 || m_labelItems[i]->size().width() != widest) {
99 m_drawer->generateLabelItem(item&: *m_labelItems[i], text: labels.at(i), widestLabel: widest);
100 }
101 }
102 }
103 m_labels = labels;
104 }
105}
106
107void AxisRenderCache::updateAllPositions()
108{
109 // As long as grid and subgrid lines are drawn identically, we can further optimize
110 // by caching all grid and subgrid positions into a single list.
111 // If subgrid lines are ever themed separately, this array will probably become obsolete.
112 if (m_formatter) {
113 int gridCount = m_formatter->gridPositions().size();
114 int subGridCount = m_formatter->subGridPositions().size();
115 int labelCount = m_formatter->labelPositions().size();
116 int fullSize = gridCount + subGridCount;
117
118 m_adjustedGridLinePositions.resize(size: fullSize);
119 m_adjustedLabelPositions.resize(size: labelCount);
120 int index = 0;
121 int grid = 0;
122 int label = 0;
123 float position = 0.0f;
124 for (; label < labelCount; label++) {
125 position = m_formatter->labelPositions().at(i: label);
126 if (m_reversed)
127 position = 1.0f - position;
128 m_adjustedLabelPositions[label] = position * m_scale + m_translate;
129 }
130 for (; grid < gridCount; grid++) {
131 position = m_formatter->gridPositions().at(i: grid);
132 if (m_reversed)
133 position = 1.0f - position;
134 m_adjustedGridLinePositions[index++] = position * m_scale + m_translate;
135 }
136 for (int subGrid = 0; subGrid < subGridCount; subGrid++) {
137 position = m_formatter->subGridPositions().at(i: subGrid);
138 if (m_reversed)
139 position = 1.0f - position;
140 m_adjustedGridLinePositions[index++] = position * m_scale + m_translate;
141 }
142
143 m_positionsDirty = false;
144 }
145}
146
147void AxisRenderCache::updateTextures()
148{
149 m_font = m_drawer->font();
150
151 if (m_title.isEmpty())
152 m_titleItem.clear();
153 else
154 m_drawer->generateLabelItem(item&: m_titleItem, text: m_title);
155
156 int widest = maxLabelWidth(labels: m_labels);
157
158 for (int i = 0; i < m_labels.size(); i++) {
159 if (m_labels.at(i).isEmpty())
160 m_labelItems[i]->clear();
161 else
162 m_drawer->generateLabelItem(item&: *m_labelItems[i], text: m_labels.at(i), widestLabel: widest);
163 }
164}
165
166void AxisRenderCache::clearLabels()
167{
168 m_titleItem.clear();
169 for (int i = 0; i < m_labels.size(); i++)
170 m_labelItems[i]->clear();
171}
172
173int AxisRenderCache::maxLabelWidth(const QStringList &labels) const
174{
175 int labelWidth = 0;
176 QFont labelFont = m_font;
177 labelFont.setPointSize(textureFontSize);
178 QFontMetrics labelFM(labelFont);
179 for (int i = 0; i < labels.size(); i++) {
180 int newWidth = labelFM.horizontalAdvance(labels.at(i));
181 if (labelWidth < newWidth)
182 labelWidth = newWidth;
183 }
184 return labelWidth;
185}
186
187QT_END_NAMESPACE
188

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtdatavis3d/src/datavisualization/engine/axisrendercache.cpp