summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Nienhüser <nienhueser@kde.org>2016-11-06 13:29:01 (GMT)
committerDennis Nienhüser <nienhueser@kde.org>2016-11-06 13:29:01 (GMT)
commit09ecae215464886d7cc5896ac263227013b830f8 (patch)
tree280e84ca6a244ea57020a6bf859121971d59378c
parent63dc14328a38e901ae4d86af3babbde5c1c78415 (diff)
Improve visible placemark caching. Lazy label pixmap creation.
Deleted placemarks (e.g. tile removed in vector osm) were kept in the cache forever with their visible placemark counterpart only being deleted on a style change (~map theme change). Placemarks that moved out of the viewport but not being deleted directly however had their visible placemark counterpart deleted directly, leading to a costly recreation when the placemark moved back into the viewport soon after. Now visible placemarks are cached only in an area around the viewport, and eventually cleaned up when their placemark counterpart is deleted. Lazy label pixmap creation is useful since some placemarks will never have their label shown, its creation however is rather costly due to the painter path involved (with glow style).
-rw-r--r--src/lib/marble/PlacemarkLayout.cpp29
-rw-r--r--src/lib/marble/PlacemarkLayout.h2
-rw-r--r--src/lib/marble/VisiblePlacemark.cpp23
-rw-r--r--src/lib/marble/VisiblePlacemark.h9
-rw-r--r--src/lib/marble/layers/PlacemarkLayer.cpp7
5 files changed, 49 insertions, 21 deletions
diff --git a/src/lib/marble/PlacemarkLayout.cpp b/src/lib/marble/PlacemarkLayout.cpp
index 436155f..0132021 100644
--- a/src/lib/marble/PlacemarkLayout.cpp
+++ b/src/lib/marble/PlacemarkLayout.cpp
@@ -361,6 +361,7 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
// First handle the selected placemarks as they have the highest priority.
const QModelIndexList selectedIndexes = m_selectionModel->selection().indexes();
+ auto const viewLatLonAltBox = viewport->viewLatLonAltBox();
for ( int i = 0; i < selectedIndexes.count(); ++i ) {
const QModelIndex index = selectedIndexes.at( i );
@@ -374,14 +375,13 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
qreal x = 0;
qreal y = 0;
- if ( !viewport->viewLatLonAltBox().contains( coordinates ) ||
+ if ( !viewLatLonAltBox.contains( coordinates ) ||
! viewport->screenCoordinates( coordinates, x, y ))
{
- delete m_visiblePlacemarks.take( placemark );
continue;
}
- if( layoutPlacemark( placemark, x, y, true) ) {
+ if( layoutPlacemark( placemark, coordinates, x, y, true) ) {
// Make sure not to draw more placemarks on the screen than
// specified by placemarksOnScreenLimit().
if ( placemarksOnScreenLimit( viewport->size() ) )
@@ -400,7 +400,6 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
}
qSort(placemarkList.begin(), placemarkList.end(), GeoDataPlacemark::placemarkLayoutOrderCompare);
- auto const viewLatLonAltBox = viewport->viewLatLonAltBox();
foreach ( const GeoDataPlacemark *placemark, placemarkList ) {
const GeoDataCoordinates coordinates = placemarkIconCoordinates( placemark );
if ( !coordinates.isValid() ) {
@@ -417,7 +416,6 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
if ( !viewLatLonAltBox.contains( coordinates ) ||
! viewport->screenCoordinates( coordinates, x, y )) {
- delete m_visiblePlacemarks.take( placemark );
continue;
}
@@ -471,7 +469,7 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
// we check for the selected state after all other filters
bool isSelected = false;
foreach ( const QModelIndex &index, selection.indexes() ) {
- const GeoDataPlacemark *mark = dynamic_cast<GeoDataPlacemark*>(qvariant_cast<GeoDataObject*>(index.data( MarblePlacemarkModel::ObjectPointerRole ) ));
+ const GeoDataPlacemark *mark = static_cast<GeoDataPlacemark*>(qvariant_cast<GeoDataObject*>(index.data( MarblePlacemarkModel::ObjectPointerRole ) ));
if (mark == placemark ) {
isSelected = true;
break;
@@ -480,7 +478,7 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
if ( isSelected )
continue;
- if( layoutPlacemark( placemark, x, y, isSelected ) ) {
+ if( layoutPlacemark( placemark, coordinates, x, y, isSelected ) ) {
// Make sure not to draw more placemarks on the screen than
// specified by placemarksOnScreenLimit().
if ( placemarksOnScreenLimit( viewport->size() ) )
@@ -488,6 +486,19 @@ QVector<VisiblePlacemark *> PlacemarkLayout::generateLayout( const ViewportParam
}
}
+ if (m_visiblePlacemarks.size() > qMax(100, 4 * m_paintOrder.size())) {
+ auto const extendedBox = viewLatLonAltBox.scaled(2.0, 2.0);
+ QVector<VisiblePlacemark*> outdated;
+ for (auto placemark: m_visiblePlacemarks) {
+ if (!extendedBox.contains(placemark->coordinates())) {
+ outdated << placemark;
+ }
+ }
+ for (auto placemark: outdated) {
+ delete m_visiblePlacemarks.take(placemark->placemark());
+ }
+ }
+
m_runtimeTrace = QStringLiteral("Placemarks: %1 Drawn: %2").arg(placemarkList.count()).arg(m_paintOrder.size());
return m_paintOrder;
}
@@ -502,7 +513,7 @@ QList<VisiblePlacemark *> PlacemarkLayout::visiblePlacemarks() const
return m_visiblePlacemarks.values();
}
-bool PlacemarkLayout::layoutPlacemark( const GeoDataPlacemark *placemark, qreal x, qreal y, bool selected )
+bool PlacemarkLayout::layoutPlacemark( const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, qreal x, qreal y, bool selected )
{
// Find the corresponding visible placemark
VisiblePlacemark *mark = m_visiblePlacemarks.value( placemark );
@@ -513,7 +524,7 @@ bool PlacemarkLayout::layoutPlacemark( const GeoDataPlacemark *placemark, qreal
// @todo: Set / adjust to tile level
parameters.placemark = placemark;
- mark = new VisiblePlacemark(placemark, m_styleBuilder->createStyle(parameters));
+ mark = new VisiblePlacemark(placemark, coordinates, m_styleBuilder->createStyle(parameters));
m_visiblePlacemarks.insert( placemark, mark );
connect( mark, SIGNAL(updateNeeded()), this, SIGNAL(repaintNeeded()) );
}
diff --git a/src/lib/marble/PlacemarkLayout.h b/src/lib/marble/PlacemarkLayout.h
index f53ddc3..c4c8f88 100644
--- a/src/lib/marble/PlacemarkLayout.h
+++ b/src/lib/marble/PlacemarkLayout.h
@@ -116,7 +116,7 @@ class PlacemarkLayout : public QObject
void styleReset();
static QSet<TileId> visibleTiles( const ViewportParams *viewport );
- bool layoutPlacemark( const GeoDataPlacemark *placemark, qreal x, qreal y, bool selected );
+ bool layoutPlacemark(const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, qreal x, qreal y, bool selected );
/**
* Returns the coordinates at which an icon should be drawn for the @p placemark.
diff --git a/src/lib/marble/VisiblePlacemark.cpp b/src/lib/marble/VisiblePlacemark.cpp
index bde76a0..15dd6c7 100644
--- a/src/lib/marble/VisiblePlacemark.cpp
+++ b/src/lib/marble/VisiblePlacemark.cpp
@@ -26,16 +26,17 @@
using namespace Marble;
-VisiblePlacemark::VisiblePlacemark( const GeoDataPlacemark *placemark, const GeoDataStyle::ConstPtr &style )
+VisiblePlacemark::VisiblePlacemark( const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, const GeoDataStyle::ConstPtr &style )
: m_placemark( placemark ),
m_selected( false ),
- m_style(style)
+ m_labelDirty(true),
+ m_style(style),
+ m_coordinates(coordinates)
{
const RemoteIconLoader *remoteLoader = style->iconStyle().remoteIconLoader();
QObject::connect( remoteLoader, SIGNAL(iconReady()),
this, SLOT(setSymbolPixmap()) );
- drawLabelPixmap();
setSymbolPixmap();
}
@@ -58,7 +59,7 @@ void VisiblePlacemark::setSelected( bool selected )
{
if (selected != m_selected) {
m_selected = selected;
- drawLabelPixmap();
+ m_labelDirty = true;
}
}
@@ -107,8 +108,12 @@ void VisiblePlacemark::setSymbolPosition( const QPointF& position )
m_symbolPosition = position;
}
-const QPixmap& VisiblePlacemark::labelPixmap() const
+const QPixmap& VisiblePlacemark::labelPixmap()
{
+ if (m_labelDirty) {
+ drawLabelPixmap();
+ }
+
return m_labelPixmap;
}
@@ -136,7 +141,7 @@ void VisiblePlacemark::setLabelRect( const QRectF& labelRect )
void VisiblePlacemark::setStyle(const GeoDataStyle::ConstPtr &style)
{
m_style = style;
- drawLabelPixmap();
+ m_labelDirty = true;
setSymbolPixmap();
}
@@ -155,8 +160,14 @@ QRectF VisiblePlacemark::boundingBox() const
return m_labelRect.isEmpty() ? symbolRect() : m_labelRect.united(symbolRect());
}
+const GeoDataCoordinates &VisiblePlacemark::coordinates() const
+{
+ return m_coordinates;
+}
+
void VisiblePlacemark::drawLabelPixmap()
{
+ m_labelDirty = false;
QString labelName = m_placemark->displayName();
if ( labelName.isEmpty() || m_style->labelStyle().color() == QColor(Qt::transparent) ) {
m_labelPixmap = QPixmap();
diff --git a/src/lib/marble/VisiblePlacemark.h b/src/lib/marble/VisiblePlacemark.h
index 25a39a2..f0eff24 100644
--- a/src/lib/marble/VisiblePlacemark.h
+++ b/src/lib/marble/VisiblePlacemark.h
@@ -22,6 +22,7 @@
#include <QRectF>
#include <GeoDataStyle.h>
+#include <GeoDataCoordinates.h>
namespace Marble
{
@@ -41,7 +42,7 @@ class VisiblePlacemark : public QObject
Q_OBJECT
public:
- explicit VisiblePlacemark(const GeoDataPlacemark *placemark, const GeoDataStyle::ConstPtr &style);
+ explicit VisiblePlacemark(const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, const GeoDataStyle::ConstPtr &style);
/**
* Returns the index of the place mark model which
@@ -82,7 +83,7 @@ class VisiblePlacemark : public QObject
/**
* Returns the pixmap of the place mark name label.
*/
- const QPixmap& labelPixmap() const;
+ const QPixmap& labelPixmap();
/**
* Returns the area covered by the place mark name label on the map.
@@ -108,6 +109,8 @@ class VisiblePlacemark : public QObject
QRectF boundingBox() const;
+ const GeoDataCoordinates & coordinates() const;
+
Q_SIGNALS:
void updateNeeded();
@@ -124,10 +127,12 @@ private Q_SLOTS:
QPointF m_symbolPosition; // position of the placemark's symbol
bool m_selected; // state of the placemark
QPixmap m_labelPixmap; // the text label (most often name)
+ bool m_labelDirty;
QRectF m_labelRect; // bounding box of label
mutable QPixmap m_symbolPixmap; // cached value
GeoDataStyle::ConstPtr m_style;
+ GeoDataCoordinates m_coordinates;
};
}
diff --git a/src/lib/marble/layers/PlacemarkLayer.cpp b/src/lib/marble/layers/PlacemarkLayer.cpp
index bec4d36..cd6ea40 100644
--- a/src/lib/marble/layers/PlacemarkLayer.cpp
+++ b/src/lib/marble/layers/PlacemarkLayer.cpp
@@ -20,6 +20,7 @@
#include "GeoDataStyle.h"
#include "GeoPainter.h"
#include "GeoDataPlacemark.h"
+#include "GeoDataLatLonAltBox.h"
#include "ViewportParams.h"
#include "VisiblePlacemark.h"
#include "RenderState.h"
@@ -210,15 +211,16 @@ bool PlacemarkLayer::testXBug()
void PlacemarkLayer::renderDebug(GeoPainter *painter, ViewportParams *viewport, const QVector<VisiblePlacemark *> &placemarks)
{
- Q_UNUSED(viewport);
painter->save();
painter->setBrush(QBrush(Qt::NoBrush));
+ auto const latLonAltBox = viewport->viewLatLonAltBox();
typedef QSet<VisiblePlacemark*> Placemarks;
Placemarks const hidden = Placemarks::fromList(m_layout.visiblePlacemarks()).subtract(Placemarks::fromList(placemarks.toList()));
- painter->setPen(QPen(QColor(Qt::red)));
for (auto placemark: hidden) {
+ bool const inside = latLonAltBox.contains(placemark->coordinates());
+ painter->setPen(QPen(QColor(inside ? Qt::red : Qt::darkYellow)));
painter->drawRect(placemark->boundingBox());
}
@@ -235,7 +237,6 @@ void PlacemarkLayer::renderDebug(GeoPainter *painter, ViewportParams *viewport,
painter->drawText(placemark->symbolRect().bottomLeft(), popularity);
}
-
painter->restore();
}