1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtLocation module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36
37 #include "qmappolygonobjectqsg_p_p.h"
38 #include <QtQuick/qsgnode.h>
39 #include <QtQuick/qsgsimplerectnode.h>
40 #include <QtPositioning/private/qgeopolygon_p.h>
41
42 QT_BEGIN_NAMESPACE
43
QMapPolygonObjectPrivateQSG(QGeoMapObject * q)44 QMapPolygonObjectPrivateQSG::QMapPolygonObjectPrivateQSG(QGeoMapObject *q)
45 : QMapPolygonObjectPrivateDefault(q)
46 {
47
48 }
49
QMapPolygonObjectPrivateQSG(const QMapPolygonObjectPrivate & other)50 QMapPolygonObjectPrivateQSG::QMapPolygonObjectPrivateQSG(const QMapPolygonObjectPrivate &other)
51 : QMapPolygonObjectPrivateDefault(other)
52 {
53 // Data already cloned by the *Default copy constructor, but necessary
54 // update operations triggered only by setters overrides
55 markSourceDirty();
56 updateGeometry();
57 if (m_map)
58 emit m_map->sgNodeChanged();
59 }
60
~QMapPolygonObjectPrivateQSG()61 QMapPolygonObjectPrivateQSG::~QMapPolygonObjectPrivateQSG()
62 {
63 if (m_map)
64 m_map->removeMapObject(q);
65 }
66
setPath(const QList<QGeoCoordinate> & p)67 void QMapPolygonObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &p)
68 {
69 if (p == path())
70 return;
71 QMapPolygonObjectPrivateDefault::setPath(p);
72 markSourceDirty();
73 updateGeometry();
74
75 if (m_map)
76 emit m_map->sgNodeChanged();
77 emit static_cast<QMapPolygonObject *>(q)->pathChanged();
78 }
79
setFillColor(const QColor & color)80 void QMapPolygonObjectPrivateQSG::setFillColor(const QColor &color)
81 {
82 QMapPolygonObjectPrivateDefault::setFillColor(color);
83
84 if (m_map)
85 emit m_map->sgNodeChanged();
86 }
87
setBorderColor(const QColor & color)88 void QMapPolygonObjectPrivateQSG::setBorderColor(const QColor &color)
89 {
90 QMapPolygonObjectPrivateDefault::setBorderColor(color);
91
92 if (m_map)
93 emit m_map->sgNodeChanged();
94 }
95
setBorderWidth(qreal width)96 void QMapPolygonObjectPrivateQSG::setBorderWidth(qreal width)
97 {
98 QMapPolygonObjectPrivateDefault::setBorderWidth(width);
99
100 if (m_map)
101 emit m_map->sgNodeChanged();
102 }
103
clone()104 QGeoMapObjectPrivate *QMapPolygonObjectPrivateQSG::clone()
105 {
106 return new QMapPolygonObjectPrivateQSG(static_cast<QMapPolygonObjectPrivate &>(*this));
107 }
108
setGeoShape(const QGeoShape & shape)109 void QMapPolygonObjectPrivateQSG::setGeoShape(const QGeoShape &shape)
110 {
111 if (shape == m_path)
112 return;
113
114 m_path = QGeoPathEager(shape);
115 markSourceDirty();
116 updateGeometry();
117 if (m_map)
118 emit m_map->sgNodeChanged();
119 emit static_cast<QMapPolygonObject *>(q)->pathChanged();
120 }
121
122 // This is called both when data changes and when viewport changes.
123 // so handle both cases (sourceDirty, !sourceDirty)
updateGeometry()124 void QMapPolygonObjectPrivateQSG::updateGeometry()
125 {
126 if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
127 return;
128
129 if (m_path.path().length() == 0) { // Possibly cleared
130 m_geometry.clear();
131 m_borderGeometry.clear();
132 return;
133 }
134 const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
135 if (m_geometry.isSourceDirty() || m_borderGeometry.isSourceDirty()) {
136 // This works a bit differently than MapPolygon:
137 // the "screen bounds" aren't needed, so update only sources,
138 // regardless of the color, as color changes won't trigger polish(),
139 // and remember to flag m_dataChanged, that is in principle the same as
140 // sourceDirty_, but in practice is cleared in two different codepaths.
141 // sourceDirty_ is cleared in any case, dataChanged only if the primitive
142 // is effectively visible (e.g., not transparent or border not null)
143 m_geometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
144 m_borderGeometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
145 m_geometry.m_dataChanged = m_borderGeometry.m_dataChanged = true;
146 m_geometry.updateSourcePoints(*m_map, m_path);
147 m_borderGeometry.updateSourcePoints(*m_map, m_path);
148 m_leftBoundMercator = p.geoToMapProjection(m_geometry.origin());
149 }
150 m_geometry.markScreenDirty(); // ToDo: this needs refactor. It's useless, remove screenDirty_ altogether.
151 m_borderGeometry.markScreenDirty();
152 m_borderGeometry.m_wrapOffset = m_geometry.m_wrapOffset = p.projectionWrapFactor(m_leftBoundMercator) + 1;
153 }
154
updateMapObjectNode(QSGNode * oldNode,VisibleNode ** visibleNode,QSGNode * root,QQuickWindow *)155 QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
156 VisibleNode **visibleNode,
157 QSGNode *root,
158 QQuickWindow * /*window*/)
159 {
160 if (!m_rootNode || !oldNode) {
161 m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
162 m_node = new MapPolygonNodeGL();
163 m_rootNode->appendChildNode(m_node);
164 m_polylinenode = new MapPolylineNodeOpenGLExtruded();
165 m_rootNode->appendChildNode(m_polylinenode);
166 m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
167 *visibleNode = static_cast<VisibleNode *>(m_rootNode);
168 if (oldNode)
169 delete oldNode;
170 } else {
171 m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
172 }
173
174 const QMatrix4x4 &combinedMatrix = m_map->geoProjection().qsgTransform();
175 const QDoubleVector3D &cameraCenter = m_map->geoProjection().centerMercator();
176
177 if (m_borderGeometry.isScreenDirty()) {
178 /* Do the border update first */
179 m_polylinenode->update(borderColor(),
180 float(borderWidth()),
181 &m_borderGeometry,
182 combinedMatrix,
183 cameraCenter,
184 Qt::SquareCap,
185 true);
186 m_borderGeometry.setPreserveGeometry(false);
187 m_borderGeometry.markClean();
188 }
189 if (m_geometry.isScreenDirty()) {
190 m_node->update(fillColor(),
191 &m_geometry,
192 combinedMatrix,
193 cameraCenter);
194 m_geometry.setPreserveGeometry(false);
195 m_geometry.markClean();
196 }
197
198 if (!m_polylinenode->isSubtreeBlocked() || !m_node->isSubtreeBlocked()) {
199 m_rootNode->setSubtreeBlocked(false);
200 root->appendChildNode(m_rootNode);
201 return m_rootNode;
202 } else {
203 m_rootNode->setSubtreeBlocked(true);
204 // If the object is currently invisible, but not gone,
205 // it is reasonable to assume it will become visible again.
206 // However, better not to retain unused data.
207 delete m_rootNode;
208 m_rootNode = nullptr;
209 m_node = nullptr;
210 m_polylinenode = nullptr;
211 *visibleNode = nullptr;
212 return nullptr;
213 }
214 }
215
markSourceDirty()216 void QMapPolygonObjectPrivateQSG::markSourceDirty()
217 {
218 m_geometry.markSourceDirty();
219 m_borderGeometry.markSourceDirty();
220 }
221
222 QT_END_NAMESPACE
223