Skip to content

Commit

Permalink
Tweak logic regarding when a map item forces the whole layout
Browse files Browse the repository at this point in the history
to be rasterised
  • Loading branch information
nyalldawson committed Dec 17, 2017
1 parent 261492d commit d3aee95
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
20 changes: 20 additions & 0 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -377,6 +377,26 @@ bool QgsLayoutItemMap::containsWmsLayer() const
return false;
}

bool QgsLayoutItemMap::requiresRasterization() const
{
if ( QgsLayoutItem::requiresRasterization() )
return true;

// we MUST force the whole layout to render as a raster if any map item
// uses blend modes, and we are not drawing on a solid opaque background
// because in this case the map item needs to be rendered as a raster, but
// it also needs to interact with items below it
if ( !containsAdvancedEffects() )
return false;

// TODO layer transparency is probably ok to allow without forcing rasterization

if ( hasBackground() && qgsDoubleNear( backgroundColor().alphaF(), 1.0 ) )
return false;

return true;
}

bool QgsLayoutItemMap::containsAdvancedEffects() const
{
if ( QgsLayoutItem::containsAdvancedEffects() )
Expand Down
1 change: 1 addition & 0 deletions src/core/layout/qgslayoutitemmap.h
Expand Up @@ -275,6 +275,7 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
//! Returns true if the map contains a WMS layer.
bool containsWmsLayer() const;

bool requiresRasterization() const override;
bool containsAdvancedEffects() const override;

/**
Expand Down
6 changes: 3 additions & 3 deletions tests/src/python/test_qgslayoutitem.py
Expand Up @@ -46,12 +46,12 @@ def make_item(self, layout):
else:
return self.createItem(layout)

def testContainsAdvancedEffects(self):
def testRequiresRasterization(self):
l = QgsLayout(QgsProject.instance())
item = self.make_item(l)
self.assertFalse(item.containsAdvancedEffects())
self.assertFalse(item.requiresRasterization())
item.setBlendMode(QPainter.CompositionMode_SourceIn)
self.assertTrue(item.containsAdvancedEffects())
self.assertTrue(item.requiresRasterization())


class TestQgsLayoutItem(unittest.TestCase):
Expand Down
49 changes: 47 additions & 2 deletions tests/src/python/test_qgslayoutmap.py
Expand Up @@ -16,9 +16,9 @@

import os

from qgis.PyQt.QtCore import QFileInfo, QRectF
from qgis.PyQt.QtCore import QFileInfo, QRectF, QDir
from qgis.PyQt.QtXml import QDomDocument
from qgis.PyQt.QtGui import QPainter
from qgis.PyQt.QtGui import QPainter, QColor

from qgis.core import (QgsLayoutItemMap,
QgsRectangle,
Expand Down Expand Up @@ -46,6 +46,14 @@ class TestQgsComposerMap(unittest.TestCase, LayoutItemTestCase):
def setUpClass(cls):
cls.item_class = QgsLayoutItemMap

def setUp(self):
self.report = "<h1>Python QgsLayoutItemMap Tests</h1>\n"

def tearDown(self):
report_file_path = "%s/qgistest.html" % QDir.tempPath()
with open(report_file_path, 'a') as report_file:
report_file.write(self.report)

def __init__(self, methodName):
"""Run once on class initialization."""
unittest.TestCase.__init__(self, methodName)
Expand Down Expand Up @@ -92,6 +100,7 @@ def testOverviewMap(self):
checker.setColorTolerance(6)
checker.setControlPathPrefix("composer_mapoverview")
myTestResult, myMessage = checker.testLayout()
self.report += checker.report()
self.layout.removeLayoutItem(overviewMap)
assert myTestResult, myMessage

Expand All @@ -111,6 +120,7 @@ def testOverviewMapBlend(self):
checker = QgsLayoutChecker('composermap_overview_blending', self.layout)
checker.setControlPathPrefix("composer_mapoverview")
myTestResult, myMessage = checker.testLayout()
self.report += checker.report()
self.layout.removeLayoutItem(overviewMap)
assert myTestResult, myMessage

Expand All @@ -130,6 +140,7 @@ def testOverviewMapInvert(self):
checker = QgsLayoutChecker('composermap_overview_invert', self.layout)
checker.setControlPathPrefix("composer_mapoverview")
myTestResult, myMessage = checker.testLayout()
self.report += checker.report()
self.layout.removeLayoutItem(overviewMap)
assert myTestResult, myMessage

Expand All @@ -150,6 +161,7 @@ def testOverviewMapCenter(self):
checker = QgsLayoutChecker('composermap_overview_center', self.layout)
checker.setControlPathPrefix("composer_mapoverview")
myTestResult, myMessage = checker.testLayout()
self.report += checker.report()
self.layout.removeLayoutItem(overviewMap)
assert myTestResult, myMessage

Expand Down Expand Up @@ -181,6 +193,7 @@ def testMapCrs(self):
checker = QgsLayoutChecker('composermap_crs3857', layout)
checker.setControlPathPrefix("composer_map")
result, message = checker.testLayout()
self.report += checker.report()
self.assertTrue(result, message)

# overwrite CRS
Expand All @@ -192,6 +205,7 @@ def testMapCrs(self):
checker = QgsLayoutChecker('composermap_crs4326', layout)
checker.setControlPathPrefix("composer_map")
result, message = checker.testLayout()
self.report += checker.report()
self.assertTrue(result, message)

# change back to project CRS
Expand Down Expand Up @@ -222,6 +236,37 @@ def testuniqueId(self):
myMessage = 'old: %s new: %s' % (oldId, newId)
assert oldId != newId, myMessage

def testContainsAdvancedEffects(self):
map_settings = QgsMapSettings()
map_settings.setLayers([self.vector_layer])
layout = QgsLayout(QgsProject.instance())
map = QgsLayoutItemMap(layout)

self.assertFalse(map.containsAdvancedEffects())
self.vector_layer.setBlendMode(QPainter.CompositionMode_Darken)
result = map.containsAdvancedEffects()
self.vector_layer.setBlendMode(QPainter.CompositionMode_SourceOver)
self.assertTrue(result)

def testRasterization(self):
map_settings = QgsMapSettings()
map_settings.setLayers([self.vector_layer])
layout = QgsLayout(QgsProject.instance())
map = QgsLayoutItemMap(layout)

self.assertFalse(map.requiresRasterization())
self.vector_layer.setBlendMode(QPainter.CompositionMode_Darken)
self.assertFalse(map.requiresRasterization())
self.assertTrue(map.containsAdvancedEffects())

map.setBackgroundEnabled(False)
self.assertTrue(map.requiresRasterization())
map.setBackgroundEnabled(True)
map.setBackgroundColor(QColor(1, 1, 1, 1))
self.assertTrue(map.requiresRasterization())

self.vector_layer.setBlendMode(QPainter.CompositionMode_SourceOver)

def testWorldFileGeneration(self):
return
myRectangle = QgsRectangle(781662.375, 3339523.125, 793062.375, 3345223.125)
Expand Down

0 comments on commit d3aee95

Please sign in to comment.