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

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