summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorsten Rahn <rahn@kde.org>2016-11-12 12:39:24 (GMT)
committerTorsten Rahn <trahn@testo.de>2016-11-12 22:41:55 (GMT)
commit9e11b578f18ea3d905e26d7c2d2ec68563f69e44 (patch)
treeac96a78d6c01dc93cfb3012ecf471efe235a49ab
parentef5c0ba82c514798b3040dd22d662400d468ba31 (diff)
configurePainter refactoring:
The intent of the previous implementation had been mudded and was undocumented. For better optimization and maintenance the configurePainter method is split into three variants: configureForOutlinePainter, configureForInlinePainter and configureForLabelPainter. The code is documented and optimized. TODO: 1. move the save() and restore() methods out of the individual calls to embrace all calls of outline, inline and label painting. 2. refactor the drawLabelForPolyline method rely on fontsize rather than taking a full Pen.
-rw-r--r--src/apps/marble-maps/BoxedText.qml3
-rw-r--r--src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp298
-rw-r--r--src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h4
3 files changed, 234 insertions, 71 deletions
diff --git a/src/apps/marble-maps/BoxedText.qml b/src/apps/marble-maps/BoxedText.qml
index 0d817eb..acaa23b 100644
--- a/src/apps/marble-maps/BoxedText.qml
+++ b/src/apps/marble-maps/BoxedText.qml
@@ -31,8 +31,7 @@ Item {
id: label
color: "white"
anchors {
- horizontalCenter: background.horizontalCenter
- verticalCenter: background.verticalCenter
+ centerIn: background
}
}
}
diff --git a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp
index fed9c3f..20bc476 100644
--- a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp
+++ b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp
@@ -164,26 +164,19 @@ void GeoLineStringGraphicsItem::paint(GeoPainter* painter, const ViewportParams*
void GeoLineStringGraphicsItem::paintInline(GeoPainter* painter, const ViewportParams* viewport)
{
+// qDebug() << Q_FUNC_INFO;
if ( ( !viewport->resolves( m_renderLineString->latLonAltBox(), 2) ) ) {
return;
}
painter->save();
- LabelPositionFlags labelPositionFlags = NoLabel;
- QPen currentPen = configurePainter(painter, viewport, labelPositionFlags);
- GeoDataStyle::ConstPtr style = this->style();
- const GeoDataLineStyle& lineStyle = style->lineStyle();
- if (lineStyle.cosmeticOutline() && lineStyle.penStyle() == Qt::SolidLine) {
- const float currentPenWidth = currentPen.widthF();
- if (currentPenWidth > 2.5f) {
- currentPen.setWidthF(currentPenWidth - 2.0f);
- }
- currentPen.setColor(style->polyStyle().paintedColor());
- painter->setPen( currentPen );
- }
- foreach(const QPolygonF* itPolygon, m_cachedPolygons) {
- painter->drawPolyline(*itPolygon);
+ bool isValid = configurePainterForInline(painter, viewport);
+
+ if (isValid) {
+ foreach(const QPolygonF* itPolygon, m_cachedPolygons) {
+ painter->drawPolyline(*itPolygon);
+ }
}
painter->restore();
@@ -191,51 +184,57 @@ void GeoLineStringGraphicsItem::paintInline(GeoPainter* painter, const ViewportP
void GeoLineStringGraphicsItem::paintOutline(GeoPainter *painter, const ViewportParams *viewport)
{
+// qDebug() << Q_FUNC_INFO;
if ( ( !viewport->resolves( m_renderLineString->latLonAltBox(), 2) ) ) {
return;
}
painter->save();
- LabelPositionFlags labelPositionFlags = NoLabel;
- QPen currentPen = configurePainter(painter, viewport, labelPositionFlags);
- m_renderLabel = !( currentPen.widthF() < 8.0f );
- if (!( currentPen.widthF() < 2.5f )) {
+ bool isValid = configurePainterForOutline(painter, viewport);
+
+ if (isValid) {
+ m_renderLabel = painter->pen().widthF() >= 8.0f;
+
foreach(const QPolygonF* itPolygon, m_cachedPolygons) {
painter->drawPolyline(*itPolygon);
}
}
+
painter->restore();
}
void GeoLineStringGraphicsItem::paintLabel(GeoPainter *painter, const ViewportParams *viewport)
{
+// qDebug() << Q_FUNC_INFO;
if ( ( !viewport->resolves( m_renderLineString->latLonAltBox(), 2) ) ) {
return;
}
painter->save();
LabelPositionFlags labelPositionFlags = NoLabel;
- QPen currentPen = configurePainter(painter, viewport, labelPositionFlags);
+ bool isValid = configurePainterForLabel(painter, viewport, labelPositionFlags);
- GeoDataStyle::ConstPtr style = this->style();
- const GeoDataLabelStyle& labelStyle = style->labelStyle();
+ if (isValid) {
+ GeoDataStyle::ConstPtr style = this->style();
- // Activate the lines below to paint a label background which
- // prevents antialiasing overpainting glitches, but leads to
- // other glitches.
- //QColor const color = style->polyStyle().paintedColor();
- //painter->setBackground(QBrush(color));
- //painter->setBackgroundMode(Qt::OpaqueMode);
+ // Activate the lines below to paint a label background which
+ // prevents antialiasing overpainting glitches, but leads to
+ // other glitches.
+ //QColor const color = style->polyStyle().paintedColor();
+ //painter->setBackground(QBrush(color));
+ //painter->setBackgroundMode(Qt::OpaqueMode);
- painter->drawLabelsForPolygons(m_cachedPolygons, feature()->name(), FollowLine,
- labelStyle.paintedColor());
+ const GeoDataLabelStyle& labelStyle = style->labelStyle();
+ painter->drawLabelsForPolygons(m_cachedPolygons, feature()->name(), FollowLine,
+ labelStyle.paintedColor());
+ }
painter->restore();
}
-QPen GeoLineStringGraphicsItem::configurePainter(GeoPainter *painter, const ViewportParams *viewport, LabelPositionFlags &labelPositionFlags) const
-{
+bool GeoLineStringGraphicsItem::configurePainterForOutline(GeoPainter *painter, const ViewportParams *viewport) const
+{
QPen currentPen = painter->pen();
GeoDataStyle::ConstPtr style = this->style();
if (!style) {
@@ -244,76 +243,239 @@ QPen GeoLineStringGraphicsItem::configurePainter(GeoPainter *painter, const View
else {
const GeoDataLineStyle& lineStyle = style->lineStyle();
+ // To save performance we avoid making changes to the painter's pen.
+ // So we first take a copy of the actual painter pen, make changes to it
+ // and only if the resulting pen is different from the actual pen
+ // we replace the painter's pen with our new pen.
+
+ // We want to avoid the mandatory detach in QPen::setColor(),
+ // so we carefully check whether applying the setter is needed
const QColor linePaintedColor = lineStyle.paintedColor();
if (currentPen.color() != linePaintedColor) {
- currentPen.setColor(linePaintedColor);
+ if (linePaintedColor.alpha() == 255) {
+ currentPen.setColor(linePaintedColor);
+ }
+ else {
+ if ( painter->mapQuality() != Marble::HighQuality
+ && painter->mapQuality() != Marble::PrintQuality ) {
+ QColor penColor = currentPen.color();
+ penColor.setAlpha( 255 );
+ if (currentPen.color() != penColor) {
+ currentPen.setColor( penColor );
+ }
+ }
+ }
}
const float lineWidth = lineStyle.width();
const float linePhysicalWidth = lineStyle.physicalWidth();
- if (currentPen.widthF() != lineWidth || linePhysicalWidth != 0.0) {
- const float scaledLinePhysicalWidth = float(viewport->radius()) / EARTH_RADIUS * linePhysicalWidth;
- if (scaledLinePhysicalWidth < lineWidth) {
- currentPen.setWidthF(lineWidth);
- } else {
- currentPen.setWidthF(scaledLinePhysicalWidth);
- }
+ float newLineWidth = lineWidth;
+ if (linePhysicalWidth != 0.0) {
+ const float scaledLinePhysicalWidth = float(viewport->radius()) / EARTH_RADIUS * linePhysicalWidth;
+ newLineWidth = scaledLinePhysicalWidth > lineWidth
+ ? scaledLinePhysicalWidth
+ : lineWidth;
}
- else if (lineWidth != 0.0 ) {
- currentPen.setWidthF(lineWidth);
+
+ // We want to avoid the mandatory detach in QPen::setWidthF(),
+ // so we carefully check whether applying the setter is needed
+ if (currentPen.widthF() != newLineWidth && newLineWidth != 0.0) {
+ if (newLineWidth < 2.5f) {
+ return false; // Don't draw any outline and abort painter configuration early
+ }
+ currentPen.setWidthF(newLineWidth);
}
+ // No need to avoid detaches inside QPen::setCapsStyle() since Qt does that for us
const Qt::PenCapStyle lineCapStyle = lineStyle.capStyle();
- if (currentPen.capStyle() != lineCapStyle) {
- currentPen.setCapStyle(lineCapStyle);
- }
+ currentPen.setCapStyle(lineCapStyle);
+ // No need to avoid detaches inside QPen::setStyle() since Qt does that for us
if (painter->mapQuality() == HighQuality || painter->mapQuality() == PrintQuality) {
const Qt::PenStyle linePenStyle = lineStyle.penStyle();
- if (currentPen.style() != linePenStyle) {
- currentPen.setStyle(linePenStyle);
- }
+ currentPen.setStyle(linePenStyle);
if (linePenStyle == Qt::CustomDashLine) {
- currentPen.setDashPattern(lineStyle.dashPattern());
+ // We want to avoid the mandatory detach in QPen::setDashPattern(),
+ // so we carefully check whether applying the setter is needed
+ if (currentPen.dashPattern() != lineStyle.dashPattern()) {
+ currentPen.setDashPattern(lineStyle.dashPattern());
+ }
}
} else {
currentPen.setStyle(Qt::SolidLine);
}
- if ( painter->mapQuality() != Marble::HighQuality
- && painter->mapQuality() != Marble::PrintQuality ) {
- QColor penColor = currentPen.color();
- penColor.setAlpha( 255 );
- currentPen.setColor( penColor );
+ if ( painter->pen() != currentPen ) {
+ painter->setPen( currentPen );
+ }
+// else qDebug() << "Detach and painter change successfully Avoided!" << Q_FUNC_INFO;
+
+ // Skipping Background changes for Outline Painter
+ }
+
+ return true;
+}
+
+bool GeoLineStringGraphicsItem::configurePainterForInline(GeoPainter *painter, const ViewportParams *viewport) const
+{
+ QPen currentPen = painter->pen();
+ GeoDataStyle::ConstPtr style = this->style();
+ if (!style) {
+ painter->setPen( QPen() );
+ }
+ else {
+ const GeoDataLineStyle& lineStyle = style->lineStyle();
+
+ // To save performance we avoid making changes to the painter's pen.
+ // So we first take a copy of the actual painter pen, make changes to it
+ // and only if the resulting pen is different from the actual pen
+ // we replace the painter's pen with our new pen.
+
+ // We want to avoid the mandatory detach in QPen::setColor(),
+ // so we carefully check whether applying the setter is needed
+
+
+ const QColor linePaintedColor = (lineStyle.cosmeticOutline() && lineStyle.penStyle() == Qt::SolidLine)
+ ? style->polyStyle().paintedColor()
+ : lineStyle.paintedColor();
+ if (currentPen.color() != linePaintedColor) {
+ if (linePaintedColor.alpha() == 255) {
+ currentPen.setColor(linePaintedColor);
+ }
+ else {
+ if ( painter->mapQuality() != Marble::HighQuality
+ && painter->mapQuality() != Marble::PrintQuality ) {
+ QColor penColor = currentPen.color();
+ penColor.setAlpha( 255 );
+ if (currentPen.color() != penColor) {
+ currentPen.setColor( penColor );
+ }
+ }
+ }
+ }
+
+ const float lineWidth = lineStyle.width();
+ const float linePhysicalWidth = lineStyle.physicalWidth();
+ float newLineWidth = lineWidth;
+ if (linePhysicalWidth != 0.0) {
+ const float scaledLinePhysicalWidth = float(viewport->radius()) / EARTH_RADIUS * linePhysicalWidth;
+ newLineWidth = scaledLinePhysicalWidth > lineWidth
+ ? scaledLinePhysicalWidth
+ : lineWidth;
+ }
+
+ if (lineStyle.cosmeticOutline() && lineStyle.penStyle() == Qt::SolidLine) {
+ if (newLineWidth > 2.5f) {
+ newLineWidth -= 2.0f;
+ }
}
- if ( painter->pen() != currentPen )
+ // We want to avoid the mandatory detach in QPen::setWidthF(),
+ // so we carefully check whether applying the setter is needed
+ if (currentPen.widthF() != newLineWidth && newLineWidth != 0.0) {
+ if (newLineWidth < 0.5f) {
+ return false; // Don't draw any outline and abort painter configuration early
+ }
+ currentPen.setWidthF(newLineWidth);
+ }
+
+ // No need to avoid detaches inside QPen::setCapsStyle() since Qt does that for us
+ const Qt::PenCapStyle lineCapStyle = lineStyle.capStyle();
+ currentPen.setCapStyle(lineCapStyle);
+
+ // No need to avoid detaches inside QPen::setStyle() since Qt does that for us
+ if (painter->mapQuality() == HighQuality || painter->mapQuality() == PrintQuality) {
+ const Qt::PenStyle linePenStyle = lineStyle.penStyle();
+ currentPen.setStyle(linePenStyle);
+
+ if (linePenStyle == Qt::CustomDashLine) {
+ // We want to avoid the mandatory detach in QPen::setDashPattern(),
+ // so we carefully check whether applying the setter is needed
+ if (currentPen.dashPattern() != lineStyle.dashPattern()) {
+ currentPen.setDashPattern(lineStyle.dashPattern());
+ }
+ }
+ } else {
+ currentPen.setStyle(Qt::SolidLine);
+ }
+
+ if ( painter->pen() != currentPen ) {
painter->setPen( currentPen );
+ }
+// else qDebug() << "Detach and painter change successfully Avoided!" << Q_FUNC_INFO;
if (lineStyle.background()) {
+// qDebug() << "BACKGROUND";
QBrush brush = painter->background();
brush.setColor(style->polyStyle().paintedColor());
painter->setBackground( brush );
painter->setBackgroundMode( Qt::OpaqueMode );
}
-
- // label styles
- const GeoDataLabelStyle& labelStyle = style->labelStyle();
- painter->setFont(labelStyle.font() );
- switch (labelStyle.alignment()) {
- case GeoDataLabelStyle::Corner:
- case GeoDataLabelStyle::Right:
- labelPositionFlags |= LineStart;
- break;
- case GeoDataLabelStyle::Center:
- labelPositionFlags |= LineCenter;
- break;
- }
}
- return currentPen;
+ return true;
+}
+
+bool GeoLineStringGraphicsItem::configurePainterForLabel(GeoPainter *painter, const ViewportParams *viewport, LabelPositionFlags &labelPositionFlags) const
+{
+ QPen currentPen = painter->pen();
+ GeoDataStyle::ConstPtr style = this->style();
+ if (!style) {
+ painter->setPen( QPen() );
+ }
+ else {
+ const GeoDataLineStyle& lineStyle = style->lineStyle();
+
+ // To save performance we avoid making changes to the painter's pen.
+ // So we first take a copy of the actual painter pen, make changes to it
+ // and only if the resulting pen is different from the actual pen
+ // we replace the painter's pen with our new pen.
+
+ // We want to avoid the mandatory detach in QPen::setColor(),
+ // so we carefully check whether applying the setter is needed
+
+ const float lineWidth = lineStyle.width();
+ const float linePhysicalWidth = lineStyle.physicalWidth();
+ float newLineWidth = lineWidth;
+ if (linePhysicalWidth != 0.0) {
+ const float scaledLinePhysicalWidth = float(viewport->radius()) / EARTH_RADIUS * linePhysicalWidth;
+ newLineWidth = scaledLinePhysicalWidth > lineWidth
+ ? scaledLinePhysicalWidth
+ : lineWidth;
+ }
+
+ // We want to avoid the mandatory detach in QPen::setWidthF(),
+ // so we carefully check whether applying the setter is needed
+ if (currentPen.widthF() != newLineWidth && newLineWidth != 0.0) {
+ if (newLineWidth < 0.5f) {
+ return false; // Don't draw any outline and abort painter configuration early
+ }
+ currentPen.setWidthF(newLineWidth);
+ }
+
+
+ if ( painter->pen() != currentPen ) {
+ painter->setPen( currentPen );
+ }
+// else qDebug() << "Detach and painter change successfully Avoided!" << Q_FUNC_INFO;
+
+ // label styles
+ const GeoDataLabelStyle& labelStyle = style->labelStyle();
+ painter->setFont(labelStyle.font() );
+ switch (labelStyle.alignment()) {
+ case GeoDataLabelStyle::Corner:
+ case GeoDataLabelStyle::Right:
+ labelPositionFlags |= LineStart;
+ break;
+ case GeoDataLabelStyle::Center:
+ labelPositionFlags |= LineCenter;
+ break;
+ }
+ }
+
+ return true;
}
bool GeoLineStringGraphicsItem::canMerge(const GeoDataCoordinates &a, const GeoDataCoordinates &b)
diff --git a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h
index 97c6b9c..ee41933 100644
--- a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h
+++ b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h
@@ -40,7 +40,9 @@ private:
void paintOutline(GeoPainter *painter, const ViewportParams *viewport);
void paintInline(GeoPainter *painter, const ViewportParams *viewport);
void paintLabel(GeoPainter *painter, const ViewportParams *viewport);
- QPen configurePainter(GeoPainter* painter, const ViewportParams *viewport, LabelPositionFlags &labelPositionFlags) const;
+ bool configurePainterForOutline(GeoPainter* painter, const ViewportParams *viewport) const;
+ bool configurePainterForInline(GeoPainter* painter, const ViewportParams *viewport) const;
+ bool configurePainterForLabel(GeoPainter* painter, const ViewportParams *viewport, LabelPositionFlags &labelPositionFlags) const;
static bool canMerge(const GeoDataCoordinates &a, const GeoDataCoordinates &b);
const GeoDataLineString *m_lineString;