From 3f9a2a315516daeb719bfbba39b3957bba1f98f4 Mon Sep 17 00:00:00 2001
From: taba90 <46672505+taba90@users.noreply.github.com>
Date: Fri, 16 Apr 2021 14:45:56 +0200
Subject: [PATCH] [GEOS-10012] Support inclusion vendor options to disable
Style elements when rendering legends (#4950)
* [GEOS-10012] Support inclusion vendor options to disable Style elements when rendering legends
* review feedback
---
.../source/styling/sld/extensions/index.rst | 1 +
.../sld/extensions/rendering-selection.rst | 311 ++++++++++++++++++
.../BufferedImageLegendGraphicBuilder.java | 1 +
.../JSONLegendGraphicBuilder.java | 1 +
.../legendgraphic/LegendGraphicBuilder.java | 16 +
.../org/geoserver/wms/WMSTestSupport.java | 22 +-
.../wms/legendgraphic/BaseLegendTest.java | 2 +
...redImageLegendGraphicOutputFormatTest.java | 49 +++
.../JSONLegendGraphicOutputFormatTest.java | 60 ++++
.../wms/wms_1_1_1/GetMapIntegrationTest.java | 75 +++++
.../results/renderingSelectionOnRule.png | Bin 0 -> 87 bytes
.../renderingSelectionOnSymbolizer.png | Bin 0 -> 115 bytes
.../styleWithLegendSelection.sld | 76 +++++
.../styleWithLegendSelectionOnSymbolizer.sld | 86 +++++
.../wms/wms_1_1_1/LakesRenderingSelection.sld | 70 ++++
.../NamedPlacesRenderingSelection.sld | 98 ++++++
.../wms/wms_1_1_1/renderingSelectionLakes.png | Bin 0 -> 2364 bytes
.../renderingSelectionNamedPlaces.png | Bin 0 -> 1164 bytes
18 files changed, 864 insertions(+), 4 deletions(-)
create mode 100644 doc/en/user/source/styling/sld/extensions/rendering-selection.rst
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/legendgraphic/results/renderingSelectionOnRule.png
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/legendgraphic/results/renderingSelectionOnSymbolizer.png
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/legendgraphic/styleWithLegendSelection.sld
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/legendgraphic/styleWithLegendSelectionOnSymbolizer.sld
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/LakesRenderingSelection.sld
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/NamedPlacesRenderingSelection.sld
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/renderingSelectionLakes.png
create mode 100644 src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/renderingSelectionNamedPlaces.png
diff --git a/doc/en/user/source/styling/sld/extensions/index.rst b/doc/en/user/source/styling/sld/extensions/index.rst
index 43913e4e4a0..20c453bc541 100644
--- a/doc/en/user/source/styling/sld/extensions/index.rst
+++ b/doc/en/user/source/styling/sld/extensions/index.rst
@@ -19,3 +19,4 @@ Although not portable to other applications, these extensions make styling more
randomized
composite-blend/index
z-order/index
+ rendering-selection
diff --git a/doc/en/user/source/styling/sld/extensions/rendering-selection.rst b/doc/en/user/source/styling/sld/extensions/rendering-selection.rst
new file mode 100644
index 00000000000..cfa542d590b
--- /dev/null
+++ b/doc/en/user/source/styling/sld/extensions/rendering-selection.rst
@@ -0,0 +1,311 @@
+.. _rendering_selection:
+
+Rendering Selection
+====================
+
+GeoServer provides a ``VendorOption`` to define whether a particular element ``Rule``, ``FeatureTypeStyle`` or ``Symbolizer`` should be applied to a ``getLegendGraphic`` output or to a ``getMap`` output.
+
+This allows to generate legends from the SLD that can be better looking and more expressive, without the underlying complexity of the actual rendered style. Other systems have a dedicated language to build legends instead. The advantage of using the same language is that dynamic behaviors, like rule removal based on the area being rendered, can be easily retained.
+
+The vendor option is named ``inclusion``, e.g.:
+
+* legendOnly
+
+* mapOnly
+
+Valid values are:
+
+* ``legendOnly`` the element will be skipped when applying the style to the data to render map.
+* ``mapOnly`` the element will be skipped when applying the style to the data to render legend.
+* ``normal`` will have the same effect then omitting the VendorOption: the SLD element will be used for both map and legend (same effect as not specifying the vendor option).
+
+
+Take as an example the following style: for each Rule two symbolizers are defined one that will be skipped when rendering the legend and one that will be skipped when rendering the map and loads the legend icon from an external svg file.
+
+.. code-block:: xml
+
+
+
+
+ Style example
+
+
+
+
+
+ numericValue
+ 90
+
+
+
+
+
+ circle
+
+ 0xFF0000
+
+
+ 32
+
+ mapOnly
+
+
+
+
+
+ image/svg+xml
+
+ 20
+
+ legendOnly
+
+
+
+
+
+
+ numericValue
+ 90
+
+
+ numericValue
+ 180
+
+
+
+
+
+
+ circle
+
+ #6495ED
+
+
+ 32
+
+ mapOnly
+
+
+
+
+
+ image/svg+xml
+
+ 20
+
+ legendOnly
+
+
+
+
+
+
+
+
+The same result could have been obtained by defining each rule two time each one with a single symbolizer, and defining the vendor options at the rule level.
+
+.. code-block:: xml
+
+
+
+
+ Style example
+
+
+
+
+
+ numericValue
+ 90
+
+
+
+
+
+ circle
+
+ 0xFF0000
+
+
+ 32
+
+
+ mapOnly
+
+
+
+
+
+ numericValue
+ 90
+
+
+ numericValue
+ 180
+
+
+
+
+
+
+ circle
+
+ #6495ED
+
+
+ 32
+
+ mapOnly
+
+
+
+
+
+ numericValue
+ 90
+
+
+
+
+
+
+ image/svg+xml
+
+ 20
+
+ legendOnly
+
+
+
+
+
+
+ numericValue
+ 90
+
+
+ numericValue
+ 180
+
+
+
+
+
+
+
+ image/svg+xml
+
+ 20
+
+ legendOnly
+
+
+
+
+
+
+
+
+
+A third way to obtain the same result could be to define vendor options at the FeatureTypeStyle level.
+
+.. code-block:: xml
+
+
+
+
+ Style example
+
+
+
+
+
+ numericValue
+ 90
+
+
+
+
+
+ circle
+
+ 0xFF0000
+
+
+ 32
+
+
+
+
+
+
+
+ numericValue
+ 90
+
+
+ numericValue
+ 180
+
+
+
+
+
+
+ circle
+
+ #6495ED
+
+
+ 32
+
+
+
+ mapOnly
+
+
+
+
+
+ numericValue
+ 90
+
+
+
+
+
+
+ image/svg+xml
+
+ 20
+
+
+
+
+
+
+
+ numericValue
+ 90
+
+
+ numericValue
+ 180
+
+
+
+
+
+
+
+ image/svg+xml
+
+ 20
+
+
+
+ legendOnly
+
+
+
+
diff --git a/src/wms/src/main/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicBuilder.java b/src/wms/src/main/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicBuilder.java
index eef95a47c34..e53e80ec8b3 100644
--- a/src/wms/src/main/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicBuilder.java
+++ b/src/wms/src/main/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicBuilder.java
@@ -135,6 +135,7 @@ public BufferedImage buildLegendGraphic(GetLegendGraphicRequest request)
throw new NullPointerException("request.getStyle()");
}
+ gt2Style = applyRenderingSelection(gt2Style);
// get rule corresponding to the layer index
// normalize to null for NO RULE
String ruleName = legend.getRule(); // was null
diff --git a/src/wms/src/main/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicBuilder.java b/src/wms/src/main/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicBuilder.java
index f2ca598d020..d7628277547 100644
--- a/src/wms/src/main/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicBuilder.java
+++ b/src/wms/src/main/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicBuilder.java
@@ -269,6 +269,7 @@ public JSONObject buildLegendGraphic(GetLegendGraphicRequest request) {
FeatureType layer = legend.getFeatureType();
Style gt2Style = legend.getStyle();
+ gt2Style = applyRenderingSelection(gt2Style);
if (gt2Style == null) {
throw new NullPointerException("request.getStyle()");
}
diff --git a/src/wms/src/main/java/org/geoserver/wms/legendgraphic/LegendGraphicBuilder.java b/src/wms/src/main/java/org/geoserver/wms/legendgraphic/LegendGraphicBuilder.java
index acad8ec2e6d..42ecebf85c9 100644
--- a/src/wms/src/main/java/org/geoserver/wms/legendgraphic/LegendGraphicBuilder.java
+++ b/src/wms/src/main/java/org/geoserver/wms/legendgraphic/LegendGraphicBuilder.java
@@ -35,6 +35,8 @@
import org.geotools.styling.Symbolizer;
import org.geotools.styling.TextSymbolizer;
import org.geotools.styling.visitor.DpiRescaleStyleVisitor;
+import org.geotools.styling.visitor.LegendRenderingSelectorStyleVisitor;
+import org.geotools.styling.visitor.RenderingSelectorStyleVisitor;
import org.geotools.styling.visitor.RescaleStyleVisitor;
import org.geotools.styling.visitor.UomRescaleStyleVisitor;
import org.locationtech.jts.geom.Coordinate;
@@ -509,4 +511,18 @@ protected void checkForRenderingTransformations(Style gt2Style) {
}
}
}
+
+ /**
+ * Checks if any false is present in the
+ * style removing style's elements not meant to be applied to the legend.
+ *
+ * @param style the style being used to build the legend
+ * @return the style without the element not meant to be applied to obtain the legend output
+ */
+ protected Style applyRenderingSelection(Style style) {
+ RenderingSelectorStyleVisitor renderingSelectorStyleVisitor =
+ new LegendRenderingSelectorStyleVisitor();
+ style.accept(renderingSelectorStyleVisitor);
+ return (Style) renderingSelectorStyleVisitor.getCopy();
+ }
}
diff --git a/src/wms/src/test/java/org/geoserver/wms/WMSTestSupport.java b/src/wms/src/test/java/org/geoserver/wms/WMSTestSupport.java
index 745be2d1ecf..1a599fef3be 100644
--- a/src/wms/src/test/java/org/geoserver/wms/WMSTestSupport.java
+++ b/src/wms/src/test/java/org/geoserver/wms/WMSTestSupport.java
@@ -46,6 +46,7 @@
import org.geoserver.catalog.LayerGroupInfo.Mode;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
+import org.geoserver.catalog.StyleInfo;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.data.test.TestData;
@@ -460,12 +461,22 @@ protected void setupTemplate(QName featureTypeName, String template, String body
protected LayerGroupInfo createLakesPlacesLayerGroup(
Catalog catalog, LayerGroupInfo.Mode mode, LayerInfo rootLayer) throws Exception {
- return createLakesPlacesLayerGroup(catalog, "lakes_and_places", mode, rootLayer);
+ return createLakesPlacesLayerGroup(catalog, "lakes_and_places", mode, rootLayer, null);
}
protected LayerGroupInfo createLakesPlacesLayerGroup(
Catalog catalog, String name, LayerGroupInfo.Mode mode, LayerInfo rootLayer)
throws Exception {
+ return createLakesPlacesLayerGroup(catalog, name, mode, rootLayer, null);
+ }
+
+ protected LayerGroupInfo createLakesPlacesLayerGroup(
+ Catalog catalog,
+ String name,
+ LayerGroupInfo.Mode mode,
+ LayerInfo rootLayer,
+ List styleInfos)
+ throws Exception {
LayerInfo lakes = catalog.getLayerByName(getLayerId(MockData.LAKES));
LayerInfo places = catalog.getLayerByName(getLayerId(MockData.NAMED_PLACES));
@@ -480,9 +491,12 @@ protected LayerGroupInfo createLakesPlacesLayerGroup(
group.getLayers().add(lakes);
group.getLayers().add(places);
- group.getStyles().add(null);
- group.getStyles().add(null);
-
+ if (styleInfos == null) {
+ group.getStyles().add(null);
+ group.getStyles().add(null);
+ } else {
+ group.getStyles().addAll(styleInfos);
+ }
CatalogBuilder cb = new CatalogBuilder(catalog);
cb.calculateLayerGroupBounds(group);
diff --git a/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BaseLegendTest.java b/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BaseLegendTest.java
index 3b5436c8aba..73d50fd495d 100644
--- a/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BaseLegendTest.java
+++ b/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BaseLegendTest.java
@@ -47,6 +47,8 @@ protected void onSetUp(SystemTestData testData) throws Exception {
testData.addStyle("rainfall_ramp", MockData.class, catalog);
testData.addStyle("rainfall_classes", MockData.class, catalog);
testData.addStyle("rainfall_classes_nolabels", MockData.class, catalog);
+ testData.addStyle("styleWithLegendSelection", this.getClass(), catalog);
+ testData.addStyle("styleWithLegendSelectionOnSymbolizer", this.getClass(), catalog);
// add raster layer for rendering transform test
testData.addRasterLayer(
new QName("http://www.opengis.net/wcs/1.1.1", "DEM", "wcs"),
diff --git a/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicOutputFormatTest.java b/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicOutputFormatTest.java
index 9e6ce3b656c..bc9e2ffb1d4 100644
--- a/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicOutputFormatTest.java
+++ b/src/wms/src/test/java/org/geoserver/wms/legendgraphic/BufferedImageLegendGraphicOutputFormatTest.java
@@ -14,7 +14,9 @@
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
+import java.io.File;
import java.io.IOException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -43,6 +45,7 @@
import org.geotools.feature.type.AttributeTypeImpl;
import org.geotools.feature.type.GeometryDescriptorImpl;
import org.geotools.feature.type.GeometryTypeImpl;
+import org.geotools.image.test.ImageAssert;
import org.geotools.image.util.ImageUtilities;
import org.geotools.referencing.CRS;
import org.geotools.renderer.lite.RendererUtilities;
@@ -1454,6 +1457,52 @@ public void testScaleDPI() throws Exception {
assertEquals(66, this.legendProducer.h);
}
+ @org.junit.Test
+ public void testLegendRenderingSelectionInRule() throws Exception {
+ // test false set for rule
+ // works for a getLegendGraphicRequest
+ // only the yellow square should be displayed
+ GetLegendGraphicRequest req = new GetLegendGraphicRequest(null);
+ req.setWidth(20);
+ req.setHeight(20);
+
+ FeatureTypeInfo ftInfo =
+ getCatalog()
+ .getFeatureTypeByName(
+ MockData.MPOLYGONS.getNamespaceURI(),
+ MockData.MPOLYGONS.getLocalPart());
+
+ req.setLayer(ftInfo.getFeatureType());
+ req.setStyle(getCatalog().getStyleByName("styleWithLegendSelection").getStyle());
+
+ BufferedImage image = this.legendProducer.buildLegendGraphic(req);
+ URL result = getClass().getResource("./results/renderingSelectionOnRule.png");
+ ImageAssert.assertEquals(new File(result.toURI()), image, 50);
+ }
+
+ @org.junit.Test
+ public void testLegendRenderingSelectionInSymbolizer() throws Exception {
+ // test the false in a Symbolizer
+ // only the a blue square should be rendered
+ GetLegendGraphicRequest req = new GetLegendGraphicRequest(null);
+ req.setWidth(20);
+ req.setHeight(20);
+
+ FeatureTypeInfo ftInfo =
+ getCatalog()
+ .getFeatureTypeByName(
+ MockData.MPOLYGONS.getNamespaceURI(),
+ MockData.MPOLYGONS.getLocalPart());
+
+ req.setLayer(ftInfo.getFeatureType());
+ req.setStyle(
+ getCatalog().getStyleByName("styleWithLegendSelectionOnSymbolizer").getStyle());
+
+ BufferedImage image = this.legendProducer.buildLegendGraphic(req);
+ URL result = getClass().getResource("./results/renderingSelectionOnSymbolizer.png");
+ ImageAssert.assertEquals(new File(result.toURI()), image, 50);
+ }
+
/** */
private Style readSLD(String sldName) throws IOException {
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
diff --git a/src/wms/src/test/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicOutputFormatTest.java b/src/wms/src/test/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicOutputFormatTest.java
index 783a913b5f4..a5a7719954a 100644
--- a/src/wms/src/test/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicOutputFormatTest.java
+++ b/src/wms/src/test/java/org/geoserver/wms/legendgraphic/JSONLegendGraphicOutputFormatTest.java
@@ -1662,6 +1662,66 @@ public void testDescreteRaster() throws Exception {
assertEquals("intervals", colormap.get(JSONLegendGraphicBuilder.COLORMAP_TYPE));
}
+
+ @org.junit.Test
+ public void testLegendSelectionInRule() throws Exception {
+ // test that the false works with the Json
+ // output
+ GetLegendGraphicRequest req = getRequest();
+ req.setWidth(20);
+ req.setHeight(20);
+
+ FeatureTypeInfo ftInfo =
+ getCatalog()
+ .getFeatureTypeByName(
+ MockData.MPOLYGONS.getNamespaceURI(),
+ MockData.MPOLYGONS.getLocalPart());
+
+ req.setLayer(ftInfo.getFeatureType());
+ req.setStyle(getCatalog().getStyleByName("styleWithLegendSelection").getStyle());
+ req.setFormat(JSONFormat);
+ JSONObject jsonLegend = this.legendProducer.buildLegendGraphic(req);
+ JSONArray legend = jsonLegend.getJSONArray(JSONLegendGraphicBuilder.LEGEND);
+ JSONArray rules = legend.getJSONObject(0).getJSONArray("rules");
+ // only one rule should be included in the output the other one has the renderingLegend
+ // option set to false.
+ assertEquals(1, rules.size());
+ String ruleName = rules.getJSONObject(0).getString("name");
+ assertEquals("nationalpark", ruleName);
+ }
+
+ @org.junit.Test
+ public void testLegendSelectionInSymbolizer() throws Exception {
+ // test that the false option set in
+ // symbolizer works
+ // avoiding the inclusion in the final output of one of the two symbolizers
+ GetLegendGraphicRequest req = getRequest();
+ req.setWidth(20);
+ req.setHeight(20);
+
+ FeatureTypeInfo ftInfo =
+ getCatalog()
+ .getFeatureTypeByName(
+ MockData.MPOLYGONS.getNamespaceURI(),
+ MockData.MPOLYGONS.getLocalPart());
+
+ req.setLayer(ftInfo.getFeatureType());
+ req.setStyle(
+ getCatalog().getStyleByName("styleWithLegendSelectionOnSymbolizer").getStyle());
+ req.setFormat(JSONFormat);
+ JSONObject jsonLegend = this.legendProducer.buildLegendGraphic(req);
+ JSONArray rules =
+ jsonLegend
+ .getJSONArray(JSONLegendGraphicBuilder.LEGEND)
+ .getJSONObject(0)
+ .getJSONArray("rules");
+ assertEquals(1, rules.size());
+ JSONArray symbolizers = rules.getJSONObject(0).getJSONArray("symbolizers");
+ // only one symbolizer of the two defined should be present in the final output
+ // the other one has the renderingLabel option set to false
+ assertEquals(1, symbolizers.size());
+ }
+
/** @param result */
private void assertNotEmpty(JSONObject result) {
assertNotNull(result);
diff --git a/src/wms/src/test/java/org/geoserver/wms/wms_1_1_1/GetMapIntegrationTest.java b/src/wms/src/test/java/org/geoserver/wms/wms_1_1_1/GetMapIntegrationTest.java
index 9b3a722598e..56711150c2f 100644
--- a/src/wms/src/test/java/org/geoserver/wms/wms_1_1_1/GetMapIntegrationTest.java
+++ b/src/wms/src/test/java/org/geoserver/wms/wms_1_1_1/GetMapIntegrationTest.java
@@ -230,6 +230,15 @@ protected void onSetUp(SystemTestData testData) throws Exception {
testData.addStyle(
"transparencyFillWidth", "transparencyFillStyleWidth.sld", getClass(), catalog);
+ testData.addStyle(
+ "namedPlacesRenderingSelection",
+ "NamedPlacesRenderingSelection.sld",
+ getClass(),
+ catalog);
+
+ testData.addStyle(
+ "lakesRenderingSelection", "LakesRenderingSelection.sld", getClass(), catalog);
+
Map properties = new HashMap<>();
properties.put(LayerProperty.STYLE, "raster");
testData.addRasterLayer(
@@ -2292,4 +2301,70 @@ public void testTransparencyFillMosaicWithWidth() throws Exception {
assertPixel(imageFill, i, 639, Color.RED);
}
}
+
+ @Test
+ public void testNamedPlacesRenderingSelection() throws Exception {
+ // We have two set of rules in the style one for the map having
+ // test false
+ // and one for the legend having test
+ // false
+ // the final result obtained with a legend decorator should show
+ // polygons and legend icons with same colors but icons without black border
+ Catalog catalog = getCatalog();
+ File layouts = getDataDirectory().findOrCreateDir("layouts");
+ URL layout = GetMapIntegrationTest.class.getResource("../test-layout-legend-image.xml");
+ FileUtils.copyURLToFile(layout, new File(layouts, "test-layout-legend-image.xml"));
+ LayerInfo places = catalog.getLayerByName(getLayerId(MockData.NAMED_PLACES));
+ StyleInfo placesStyle = catalog.getStyleByName("namedPlacesRenderingSelection");
+ LegendInfoImpl legend = new LegendInfoImpl();
+ legend.setFormat("image/png;charset=utf-8");
+ legend.setHeight(32);
+ legend.setWidth(32);
+ placesStyle.setLegend(legend);
+ catalog.save(placesStyle);
+ places.getStyles().add(placesStyle);
+ catalog.save(places);
+ String url =
+ "wms?LAYERS="
+ + places.getName()
+ + "&STYLES=namedPlacesRenderingSelection&FORMAT=image%2Fpng"
+ + "&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG%3A4326&WIDTH=256"
+ + "&HEIGHT=256&BBOX=0.0000,-0.0020,0.0035,0.0010&format_options=layout:test-layout-legend-image";
+ BufferedImage image = getAsImage(url, "image/png");
+ URL urlPng = getClass().getResource("renderingSelectionNamedPlaces.png");
+ ImageAssert.assertEquals(new File(urlPng.toURI()), image, 1300);
+ }
+
+ @Test
+ public void testLakesWithRenderingSelection() throws Exception {
+ // We have two featureTypeStyle in the style one for the map having
+ // test false
+ // and one for the legend having test
+ // false
+ // the final result obtained with a legend decorator should show
+ // polygon and legend icon with same color but icon without black border
+ Catalog catalog = getCatalog();
+ File layouts = getDataDirectory().findOrCreateDir("layouts");
+ URL layout = GetMapIntegrationTest.class.getResource("../test-layout-legend-image.xml");
+ FileUtils.copyURLToFile(layout, new File(layouts, "test-layout-legend-image.xml"));
+ LayerInfo lakes = catalog.getLayerByName(getLayerId(MockData.LAKES));
+ StyleInfo lakesStyle = catalog.getStyleByName("lakesRenderingSelection");
+ LegendInfoImpl legend = new LegendInfoImpl();
+ legend.setFormat("image/png;charset=utf-8");
+ legend.setHeight(32);
+ legend.setWidth(32);
+ lakesStyle.setLegend(legend);
+ catalog.save(lakesStyle);
+ lakes.getStyles().add(lakesStyle);
+ catalog.save(lakes);
+ String url =
+ "wms?LAYERS="
+ + lakes.getName()
+ + "&STYLES=lakesRenderingSelection&FORMAT=image%2Fpng"
+ + "&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG%3A4326&WIDTH=256"
+ + "&HEIGHT=256&BBOX=0.0000,-0.0020,0.0035,0.0010&format_options=layout:test-layout-legend-image";
+ BufferedImage image = getAsImage(url, "image/png");
+ URL urlPng = getClass().getResource("renderingSelectionLakes.png");
+ ImageAssert.assertEquals(new File(urlPng.toURI()), image, 1300);
+ }
}
diff --git a/src/wms/src/test/resources/org/geoserver/wms/legendgraphic/results/renderingSelectionOnRule.png b/src/wms/src/test/resources/org/geoserver/wms/legendgraphic/results/renderingSelectionOnRule.png
new file mode 100644
index 0000000000000000000000000000000000000000..b4f25eb3ad20230f42ae443939fca6d4893e6efd
GIT binary patch
literal 87
zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjyIZqeIkcwN$Kl~XJBt&LOb~rDd
jmg>d5c^V7ph^Z$S3j3^P6ati~c9
+
+
+
+
+
+
+
+ tl 2010 08013 arealm
+
+
+ group 0
+ Feature
+ generic:geometry
+ simple
+
+
+ park
+
+
+ MTFCC
+ K2180
+
+
+ 500000.0
+
+
+
+
+
+
+ image/png
+
+
+
+
+
+ mapOnly
+
+
+
+ nationalpark
+
+
+ MTFCC
+ K2181
+
+
+ 500000.0
+
+
+
+
+
+ square
+
+ #ffff00
+
+
+ 6
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/wms/src/test/resources/org/geoserver/wms/legendgraphic/styleWithLegendSelectionOnSymbolizer.sld b/src/wms/src/test/resources/org/geoserver/wms/legendgraphic/styleWithLegendSelectionOnSymbolizer.sld
new file mode 100644
index 00000000000..5ce1a9ae286
--- /dev/null
+++ b/src/wms/src/test/resources/org/geoserver/wms/legendgraphic/styleWithLegendSelectionOnSymbolizer.sld
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+ tl 2010 08013 arealm
+
+
+ group 0
+ Feature
+ generic:geometry
+ simple
+
+ nationalpark
+
+
+ MTFCC
+ K2181
+
+
+
+
+ #0099cc
+
+
+ #000000
+ 0.5
+
+
+
+
+
+
+
+ circle
+
+ #ffffff
+
+
+ 4
+
+
+ rotation
+ -1
+
+
+ 0.4
+
+
+
+
+
+
+
+ square
+
+ #ffff00
+
+
+ 6
+
+
+ rotation
+ -1
+
+
+ 0.4
+
+
+
+ mapOnly
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/LakesRenderingSelection.sld b/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/LakesRenderingSelection.sld
new file mode 100644
index 00000000000..6b00f8e6e60
--- /dev/null
+++ b/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/LakesRenderingSelection.sld
@@ -0,0 +1,70 @@
+
+
+
+ Default Styler
+ Default Styler
+
+
+ Feature
+
+ name
+ Abstract
+ title
+
+
+
+ #4040C0
+
+
+ 1.0
+
+
+
+
+ #000000
+
+
+ butt
+
+
+ miter
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ mapOnly
+
+
+ Feature
+
+ name
+ Abstract
+ title
+
+
+
+ #4040C0
+
+
+ 1.0
+
+
+
+
+ legendOnly
+
+
+
diff --git a/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/NamedPlacesRenderingSelection.sld b/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/NamedPlacesRenderingSelection.sld
new file mode 100644
index 00000000000..4e1526fcd5c
--- /dev/null
+++ b/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/NamedPlacesRenderingSelection.sld
@@ -0,0 +1,98 @@
+
+
+
+ Default Styler
+ Default Styler
+
+
+ Feature
+
+ ashton
+ Ashton
+
+
+ NAME
+ Ashton
+
+
+
+
+
+ #AAAAAA
+
+
+
+
+ #000000
+
+
+
+ mapOnly
+
+
+ goose_island
+ Goose Island
+
+
+ NAME
+ Goose Island
+
+
+
+
+
+ #FF5733
+
+
+
+
+ #000000
+
+
+
+ mapOnly
+
+
+
+ ashton
+ Ashton
+
+
+ NAME
+ Ashton
+
+
+
+
+
+ #AAAAAA
+
+
+
+ legendOnly
+
+
+ goose_island
+ Goose Island
+
+
+ NAME
+ Goose Island
+
+
+
+
+
+ #FF5733
+
+
+
+ legendOnly
+
+
+
+
diff --git a/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/renderingSelectionLakes.png b/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/renderingSelectionLakes.png
new file mode 100644
index 0000000000000000000000000000000000000000..67f2f4c917ae290495bbbe90a76aa1f6b6a1f78f
GIT binary patch
literal 2364
zcmcguX;>3U8m?{Z|wtj<>q1
zx;mW*;LoAWqX7Wstnu~Q0006_1YjuaS`9pw1E8m~#%s0UtIol5fxf2>n30!?bI#T0
zDE=|eWIF3~N=w^^Z&&7ft@A9qwoEtuP-@2R)xqh^uQPUr&}OYXEx{N%oaTB@Lwn5p
zoApg~ya#laYuvC>$`jN7;9B7kbfQDCXY-lHvB{doJ0b&fuMf$M&OH;@+)&CgzcdSk
z4FC#e8Z#z)p_#qeFddKpV4oU7fIKn(B5frJft8ft9CiEn`@`+8r!4`E60B|CxWps4
zUwhydMt;YaFdk2aUP`&r9?QjxK+!Fo#L;)P>i*@3Km(#`bc%2Gn!Yi;vw4Y)=3v0RLsfpqjCgLmP&9lwT3Q
z8dm;mLjRfC?_vF-D7l!)WIE>fB_&N3Z7MYYvzNQMxw*Q|qw_tbO|KqVXFF{50mHco
zL(lyK0`|wnRmED+v!5vPCdM^ELG*ju{yG+jf#;6S&d%=c8hVx6cv
zWOYGNf5Akakq&a(`FU-Mhm%wMi@RxVFT&(rpQUf_?!J-zI7#DT9UAt`03?P*7ZnzE
zHy`&g%E&OCrE5{LYJ6S!mpx;eohw$Xz(6>s!o(zLaIpQz5mssZX!di|=Me6Z$tfSxvvnxI$
z6B=@6SN#KDhBpY)-}l4zJh3HNNzI0Mf$8RtNw!9-q*#QoE*}!A8RE$d@%Qi_OD>-e*KaWm~v@FfyfrUsyw5SVz&=PRf#Queu?V02-zMa7}oNkM!;I3#v~LG
zDFDpPLfQHmf=M-~Ru*h%71JlBQC(vLQ4DPm8RyE0t-De>?V2}dj62cEn>4=7seUHk
z+fyU*Qf|L<64a^|)PhctEEipM;LY7Fa=ASB9!;W3OY{S6Tty&aV`I}b@g~zMWdROQ
znMRsSQ`-B4bi8(an4XRH4N6(GWgZ?w_CDKRQYn}psNpJj$afvZ)w^nH5)9bOkkNMp
zgX(*!wRyMafWz@b6MPRt>rdu`Gk)j2NRmo)@{)}37@!RY8C-=kvQU>8qBcGK1YT#8
zRV;NDsMnEE5rvj0r5Lbq4kjrP3$4jv5a|WBa1|EFkGg~v+NYLIVQdew(-2?J(DK1g
zh~gMHDwKJk4Gc*ErKyF-HN?GvlQnsorA`NSsBAHEZIlS45Qg{_J;?>}IGa2TBK?60
zSD}ksqY#JDh9RjtCb1^x8RN+e?P|b56a}DOBoiXWRN^d(4N28h!WiF6W8V}Pn&Rt$
z(-QJWR$&;}f+&i?Ns(+H5=SK-qG^NDDr%Dn&e3Pf#cC$L2{_r4|6~;ggLp(y0USlL
zZHR(OyhIxYq(`ZQDQ<{IFxu?M``{=*MY15|kFyAh!BgIKnq)a?N#14^ZUh;KF+zDq
zWTCcmBpCauxX>8i1H8dOt{@+*)!AJFJXBIMv_T~ur!<-4vDBt}i%jtVM%yCtIrttM
z_yo^|?zupyV{3I)Y-fbWgPkztPE||QC*hKgP>2nJNk)lQ)BsmW
z3#e?eg*QmUfwo%gbJ4`Sh1Z6`fk>@>yw{hp(F!1np}F%DD;97CVn8AEzxAE3e@m=3
zAVK68Rn=eW_VD7Nzmwz0`zcZ+qr=ob1^K;VXruqNOuqOGlLTuSP8@)oVnv1m)RwC#
zftiKyTtHn-+s26I8EN-4(io`D5g8>aA&>)vvdz%L4{!w^{cT8=od8A~`7uoFV6Koe
zf=Jh#RUtQLU|HRt65j{j(8}dgPn(7xm2BC1_vPNqhGV_88$Qot*{z3XAoYGvTYT*F
zRC-laZ2H~hH&jRN<@>tjiA~+*{=7TqGcz;G%F4{0_xS||Ha>b(=@t!Nf(G%}>XzmD?GKVzoF0QV^-tV*ivT|aeqdYY=)tj4U
zM1rb=b!C?p^#?g5jIFT=y#G@7Li5qC^6>ER=AM*3=(wpgyarwv0|Nv7?WLw!RkN135jP=5p`wW=
zKlWMZhvOgn6iR~yj8;~HhtL^gQu|b@j%$~{R$@NX=td5Oe|5>fe=h$24P2a^0x}Oe
Uc5i*5>;mvv;~n5t;u&%1XCUdF6aWAK
literal 0
HcmV?d00001
diff --git a/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/renderingSelectionNamedPlaces.png b/src/wms/src/test/resources/org/geoserver/wms/wms_1_1_1/renderingSelectionNamedPlaces.png
new file mode 100644
index 0000000000000000000000000000000000000000..bbb53bb080f8da12c2d91248d905645aeef9d0df
GIT binary patch
literal 1164
zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLk0$xU{4pvkcwMx@A~H53J_@s
zT)%j+-h$0MyC!MfP82>PSsonA)-8s{(L?s$n5gyfy?{N^LsfD_ja9r
zYQ%H+XU)H}iaf`*Ft9WrkQHCTfEzdJ+||V
zzAlRXkQAfY@XA=No|Unrmd9Y1XWw(JpTC2Dclm^W6v_B@GyQw)G6$v^oC=$#pYVT?
zZvOdX^Me$Xk6AOAI1_6AJXL?)%|5|0da7lM$GcFUMiv8`{Y%gHKf9?JP-J_1nZwEA
zgG?{Jlr}t>n3Q>MzCD93>xCKt8!J|!28L&oHGJD21^526^r>6BD&0nwnS&v{kp;=$
z5O$xm!zXtR21W?7iCZ{f=dDG#j*J^#GW?70Dt^FFw=rFt#h~i!%_~pm{B*tcX#e7O
zx5e2Fs{ZG#@xMDWmgUs#_19SqObb@uxBOkqa=?wbLw}Pv!`-)xZu=b>WON%YexEnp
zZ8L*K0>e_xfKtI57eqL|$ue*-urM$&Fg7qaFcf@YxOYFuTmU3i@SUZz{GQGq?bh>O
zpUm3v&V!+qA#7)gFGG$}!-J*^(U;r5s+H?3HNUTNKkLuW&1O7Oj3#UX?&E$V!qwANCq9r15clS-+PDUz$eB#_wIiy5@ui$APE6e12DaF
zH~=-#f|*dvIH#`W_Gw=R9r*+MkfNLfpF1$%R;<8K&je3KxRrqt85Y?+cjE0ttf#y^
RtYyFe1fH&bF6*2UngCKURJZ^D
literal 0
HcmV?d00001