Skip to content

Commit fa157b0

Browse files
committed
Add composer svg export label unit tests
- Fix composer composition setup to near identical output of canvas->image (finally, expect for symbology, which still seems to be double-antialiased) - Rebuild control images for composer->image output
1 parent b6b78ca commit fa157b0

File tree

21 files changed

+73
-48
lines changed

21 files changed

+73
-48
lines changed

tests/src/python/test_qgspallabeling_composer.py

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -94,44 +94,50 @@ def setUp(self):
9494

9595
def _set_up_composition(self, width, height, dpi):
9696
# set up composition and add map
97-
# TODO: how to keep embedded map from being anti-aliased twice?
98-
# self._MapSettings.setFlag(QgsMapSettings.Antialiasing, False)
99-
# self._MapSettings.setFlag(QgsMapSettings.UseAdvancedEffects, True)
97+
self._TestMapSettings.setFlag(QgsMapSettings.Antialiasing, True)
98+
self._TestMapSettings.setFlag(QgsMapSettings.UseAdvancedEffects, True)
99+
self._TestMapSettings.setFlag(QgsMapSettings.ForceVectorOutput, True)
100100
self._c = QgsComposition(self._TestMapSettings)
101101
""":type: QgsComposition"""
102+
# self._c.setUseAdvancedEffects(False)
102103
self._c.setPrintResolution(dpi)
103104
# 600 x 400 px = 211.67 x 141.11 mm @ 72 dpi
104-
# TODO: figure out why this doesn't work and needs fudging
105-
# probably need sets of fudgyness per dpi group (72, 150, 300)?
106-
paperw = round((width * 25.4 / dpi) + 0.05, 0)
107-
paperh = round((height * 25.4 / dpi) + 0.05, 1)
105+
paperw = width * 25.4 / dpi
106+
paperh = height * 25.4 / dpi
108107
self._c.setPaperSize(paperw, paperh)
109-
self._cmap = QgsComposerMap(
110-
self._c, 0, 0, self._c.paperWidth(), self._c.paperHeight())
108+
# NOTE: do not use QgsComposerMap(self._c, 0, 0, paperw, paperh) since
109+
# it only takes integers as parameters and the composition will grow
110+
# larger based upon union of item scene rectangles and a slight buffer
111+
# see end of QgsComposition::compositionBounds()
112+
# add map as small graphics item first, then set its scene QRectF later
113+
self._cmap = QgsComposerMap(self._c, 10, 10, 10, 10)
111114
""":type: QgsComposerMap"""
115+
self._cmap.setPreviewMode(QgsComposerMap.Render)
112116
self._cmap.setFrameEnabled(False)
113-
self._cmap.setNewExtent(self.aoiExtent())
114117
self._c.addComposerMap(self._cmap)
118+
# now expand map to fill page and set its extent
119+
self._cmap.setSceneRect(QRectF(0, 0, paperw, paperw))
120+
self._cmap.setNewExtent(self.aoiExtent())
121+
# self._cmap.updateCachedImage()
115122
self._c.setPlotStyle(QgsComposition.Print)
116123

117124
# noinspection PyUnusedLocal
118125
def _get_composer_image(self, width, height, dpi):
119-
image = QImage(QSize(width, height), QImage.Format_ARGB32)
120-
image.fill(QColor(152, 219, 249).rgb())
121-
image.setDotsPerMeterX(dpi / 25.4 * 1000)
122-
image.setDotsPerMeterY(dpi / 25.4 * 1000)
123-
124-
p = QPainter(image)
125-
p.setRenderHint(QPainter.Antialiasing, True)
126-
p.setRenderHint(QPainter.HighQualityAntialiasing, True)
127-
self._c.renderPage(p, 0)
128-
p.end()
129-
130-
# image = self._c.printPageAsRaster(0)
131-
# """:type: QImage"""
126+
# image = QImage(QSize(width, height), QImage.Format_ARGB32)
127+
# image.fill(QColor(152, 219, 249).rgb())
128+
# image.setDotsPerMeterX(dpi / 25.4 * 1000)
129+
# image.setDotsPerMeterY(dpi / 25.4 * 1000)
130+
#
131+
# p = QPainter(image)
132+
# p.setRenderHint(QPainter.Antialiasing, False)
133+
# p.setRenderHint(QPainter.HighQualityAntialiasing, False)
134+
# self._c.renderPage(p, 0)
135+
# p.end()
136+
137+
image = self._c.printPageAsRaster(0)
138+
""":type: QImage"""
132139

133140
if image.isNull():
134-
# something went pear-shaped
135141
return False, ''
136142

137143
filepath = getTempfilePath('png')
@@ -144,31 +150,23 @@ def _get_composer_image(self, width, height, dpi):
144150

145151
def _get_composer_svg_image(self, width, height, dpi):
146152
# from qgscomposer.cpp, QgsComposer::on_mActionExportAsSVG_triggered,
147-
# line 1909, near end of function
153+
# near end of function
148154
svgpath = getTempfilePath('svg')
149155
temp_size = os.path.getsize(svgpath)
150156

151157
svg_g = QSvgGenerator()
152158
# noinspection PyArgumentList
153159
svg_g.setTitle(QgsProject.instance().title())
154160
svg_g.setFileName(svgpath)
155-
# width and height in pixels
156-
# svg_w = int(self._c.paperWidth() * self._c.printResolution() / 25.4)
157-
# svg_h = int(self._c.paperHeight() * self._c.printResolution() / 25.4)
158-
svg_w = width
159-
svg_h = height
160-
svg_g.setSize(QSize(svg_w, svg_h))
161-
svg_g.setViewBox(QRect(0, 0, svg_w, svg_h))
162-
# because the rendering is done in mm, convert the dpi
163-
# svg_g.setResolution(self._c.printResolution())
161+
svg_g.setSize(QSize(width, height))
162+
svg_g.setViewBox(QRect(0, 0, width, height))
164163
svg_g.setResolution(dpi)
165164

166165
sp = QPainter(svg_g)
167166
self._c.renderPage(sp, 0)
168167
sp.end()
169168

170169
if temp_size == os.path.getsize(svgpath):
171-
# something went pear-shaped
172170
return False, ''
173171

174172
image = QImage(width, height, QImage.Format_ARGB32)
@@ -211,7 +209,6 @@ def _get_composer_pdf_image(self, width, height, dpi):
211209
pdf_p.end()
212210

213211
if temp_size == os.path.getsize(pdfpath):
214-
# something went pear-shaped
215212
return False, ''
216213

217214
filepath = getTempfilePath('png')
@@ -260,10 +257,11 @@ def get_composer_output(self, kind):
260257
def checkTest(self, **kwargs):
261258
self.lyr.writeToLayer(self.layer)
262259
res_m, self._TestImage = self.get_composer_output(self._TestKind)
263-
self.saveControlImage(self._TestImage)
264260
self.assertTrue(res_m, 'Failed to retrieve/save output from composer')
261+
self.saveControlImage(self._TestImage)
265262
mismatch = self._Mismatch
266-
if self._TestGroup in self._Mismatches:
263+
if (self._TestGroup in self._Mismatches
264+
and 'PAL_NO_MISMATCH' not in os.environ):
267265
mismatch = self._Mismatches[self._TestGroup]
268266
self.assertTrue(*self.renderCheck(mismatch=mismatch,
269267
imgpath=self._TestImage))
@@ -295,15 +293,39 @@ def setUp(self):
295293
self.configTest('pal_canvas', 'sp')
296294

297295

296+
class TestComposerSvgPoint(TestComposerPointBase, TestPointBase):
297+
298+
def setUp(self):
299+
"""Run before each test."""
300+
super(TestComposerSvgPoint, self).setUp()
301+
self._TestKind = OutputKind.Svg
302+
self.configTest('pal_composer', 'sp_svg')
303+
304+
305+
class TestComposerSvgVsComposerPoint(TestComposerPointBase, TestPointBase):
306+
"""
307+
Compare only to composer image, which is already compared to canvas point
308+
"""
309+
def setUp(self):
310+
"""Run before each test."""
311+
super(TestComposerSvgVsComposerPoint, self).setUp()
312+
self._TestKind = OutputKind.Svg
313+
self.configTest('pal_composer', 'sp_img')
314+
315+
298316
if __name__ == '__main__':
299317
# NOTE: unless PAL_SUITE env var is set all test class methods will be run
300318
# SEE: test_qgspallabeling_tests.suiteTests() to define suite
301319
st = suiteTests()
302320
sp_i = ['TestComposerImagePoint.' + t for t in st['sp_suite']]
303321
sp_ivs = ['TestComposerImageVsCanvasPoint.' + t for t in st['sp_vs_suite']]
322+
sp_s = ['TestComposerSvgPoint.' + t for t in st['sp_suite']]
323+
sp_svs = ['TestComposerSvgVsComposerPoint.' + t for t in st['sp_vs_suite']]
304324
suite = []
305325
# extended separately for finer control of PAL_SUITE (comment-out undesired)
306326
suite.extend(sp_i)
307327
suite.extend(sp_ivs)
328+
suite.extend(sp_s)
329+
suite.extend(sp_svs)
308330
res = runSuite(sys.modules[__name__], suite)
309331
sys.exit(not res.wasSuccessful())

tests/src/python/test_qgspallabeling_server.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ def setUpClass(cls):
8282
settings = QSettings()
8383
# noinspection PyArgumentList
8484
cls._CacheDir = settings.value(
85-
"cache/directory", QgsApplication.qgisSettingsDirPath() + "cache")
85+
"cache/directory",
86+
os.path.join(QgsApplication.qgisSettingsDirPath(), "cache"),
87+
type=unicode)
8688

8789
@classmethod
8890
def tearDownClass(cls):

tests/src/python/test_qgspallabeling_tests.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
__revision__ = '$Format:%H$'
1616

1717
import os
18-
import sys
1918
from PyQt4.QtCore import *
2019
from PyQt4.QtGui import *
2120

@@ -44,9 +43,14 @@ def __init__(self):
4443
# e.g. self._Mismatches['TestClassName'] = 300
4544
self._Mismatches = dict()
4645

46+
# noinspection PyMethodMayBeStatic
47+
def checkTest(self, **kwargs):
48+
"""Intended to be overridden in subclasses"""
49+
pass
50+
4751
def test_default_label(self):
4852
# Default label placement, with text size in points
49-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2034
53+
self._Mismatches['TestComposerSvgVsComposerPoint'] = 500
5054
self.checkTest()
5155

5256
def test_text_size_map_unit(self):
@@ -55,18 +59,17 @@ def test_text_size_map_unit(self):
5559
font = QFont(self._TestFont)
5660
font.setPointSizeF(460)
5761
self.lyr.textFont = font
58-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 1877
5962
self.checkTest()
6063

6164
def test_text_color(self):
6265
# Label color change
6366
self.lyr.textColor = Qt.blue
64-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2034
67+
self._Mismatches['TestComposerSvgVsComposerPoint'] = 500
6568
self.checkTest()
6669

6770
def test_background_rect(self):
6871
self.lyr.shapeDraw = True
69-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2751
72+
self._Mismatches['TestComposerSvgVsComposerPoint'] = 1100
7073
self.checkTest()
7174

7275
def test_background_rect_w_offset(self):
@@ -82,7 +85,7 @@ def test_background_rect_w_offset(self):
8285
self.lyr.shapeDraw = True
8386
self.lyr.shapeOffsetUnits = QgsPalLayerSettings.MapUnits
8487
self.lyr.shapeOffset = QPointF(-2900.0, -450.0)
85-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2530
88+
self._Mismatches['TestComposerSvgVsComposerPoint'] = 750
8689
self.checkTest()
8790

8891
def test_background_svg(self):
@@ -100,7 +103,6 @@ def test_background_svg(self):
100103
self.lyr.shapeSizeUnits = QgsPalLayerSettings.MapUnits
101104
self.lyr.shapeSizeType = QgsPalLayerSettings.SizeBuffer
102105
self.lyr.shapeSize = QPointF(100.0, 0.0)
103-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2882
104106
self.checkTest()
105107

106108
def test_background_svg_w_offset(self):
@@ -121,7 +123,6 @@ def test_background_svg_w_offset(self):
121123

122124
self.lyr.shapeOffsetUnits = QgsPalLayerSettings.MapUnits
123125
self.lyr.shapeOffset = QPointF(-2850.0, 500.0)
124-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2901
125126
self.checkTest()
126127

127128
def test_partials_labels_enabled(self):
@@ -132,7 +133,7 @@ def test_partials_labels_enabled(self):
132133
# Enable partials labels
133134
self._Pal.setShowingPartialsLabels(True)
134135
self._Pal.saveEngineSettings()
135-
self._Mismatches['TestComposerImageVsCanvasPoint'] = 2250
136+
self._Mismatches['TestComposerSvgVsComposerPoint'] = 600
136137
self.checkTest()
137138

138139
def test_partials_labels_disabled(self):
80 Bytes
Loading
-62 Bytes
Loading
-43 Bytes
Loading
-51 Bytes
Loading
0 Bytes
Loading
-42 Bytes
Loading
31 Bytes
Loading

0 commit comments

Comments
 (0)