*/
public void produceMap() throws WmsException {
try {
findDecorationLayout(mapContext);
} catch (Exception e) {
throw new WmsException(e);
}
Rectangle paintArea = new Rectangle(
0, 0,
mapContext.getMapWidth(), mapContext.getMapHeight()
);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("setting up " + paintArea.width + "x" + paintArea.height + " image");
}
// extra antialias setting
final GetMapRequest request = mapContext.getRequest();
String antialias = (String) request.getFormatOptions().get("antialias");
if (antialias != null)
antialias = antialias.toUpperCase();
// figure out a palette for buffered image creation
IndexColorModel palette = null;
final InverseColorMapOp paletteInverter = mapContext
.getPaletteInverter();
final boolean transparent = mapContext.isTransparent();
final Color bgColor = mapContext.getBgColor();
if (paletteInverter != null && AA_NONE.equals(antialias)) {
palette = paletteInverter.getIcm();
} else if (AA_NONE.equals(antialias)) {
PaletteExtractor pe = new PaletteExtractor(transparent ? null : bgColor);
MapLayer[] layers = mapContext.getLayers();
for (int i = 0; i < layers.length; i++) {
pe.visit(layers[i].getStyle());
if (!pe.canComputePalette())
break;
}
if (pe.canComputePalette())
palette = pe.getPalette();
}
// before even preparing the rendering surface, check it's not too big,
// if so, throw a service exception
long maxMemory = wms.getMaxRequestMemory() * KB;
// ... base image memory
long memory = getDrawingSurfaceMemoryUse(paintArea.width, paintArea.height, palette, transparent);
// .. use a fake streaming renderer to evaluate the extra back buffers used when rendering
// multiple featureTypeStyles against the same layer
StreamingRenderer testRenderer = new StreamingRenderer();
testRenderer.setContext(mapContext);
memory += testRenderer.getMaxBackBufferMemory(paintArea.width, paintArea.height);
if(maxMemory > 0 && memory > maxMemory) {
long kbUsed = memory / KB;
long kbMax = maxMemory / KB;
throw new WmsException("Rendering request would use " + kbUsed + "KB, whilst the " +
"maximum memory allowed is " + kbMax + "KB");
}
// we use the alpha channel if the image is transparent or if the meta tiler
// is enabled, since apparently the Crop operation inside the meta-tiler
// generates striped images in that case (see GEOS-
boolean useAlpha = transparent || MetatileMapProducer.isRequestTiled(request, this);
final RenderedImage preparedImage = prepareImage(paintArea.width, paintArea.height,
palette, useAlpha);
final Map<RenderingHints.Key, Object> hintsMap = new HashMap<RenderingHints.Key, Object>();
final Graphics2D graphic = ImageUtils.prepareTransparency(transparent, bgColor,
preparedImage, hintsMap);
// set up the antialias hints
if (AA_NONE.equals(antialias)) {
hintsMap.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
if (preparedImage.getColorModel() instanceof IndexColorModel) {
// otherwise we end up with dithered colors where the match is
// not 100%
hintsMap.put(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
}
} else if (AA_TEXT.equals(antialias)) {
hintsMap.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
hintsMap.put(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
} else {
if (antialias != null && !AA_FULL.equals(antialias)) {
LOGGER.warning("Unrecognized antialias setting '" + antialias
+ "', valid values are " + AA_SETTINGS);
}
hintsMap.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
// turn off/on interpolation rendering hint
if(wms != null) {
if (WMSInterpolation.Nearest.equals(wms.getInterpolation())) {
hintsMap.put(JAI.KEY_INTERPOLATION, NN_INTERPOLATION);
hintsMap.put(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
} else if (WMSInterpolation.Bilinear.equals(wms.getInterpolation())) {
hintsMap.put(JAI.KEY_INTERPOLATION, BIL_INTERPOLATION);
hintsMap.put(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
} else if (WMSInterpolation.Bicubic.equals(wms.getInterpolation())) {
hintsMap.put(JAI.KEY_INTERPOLATION, BIC_INTERPOLATION);
hintsMap.put(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
}
}
// line look better with this hint, they are less blurred
hintsMap.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
// make sure the hints are set before we start rendering the map
graphic.setRenderingHints(hintsMap);
RenderingHints hints = new RenderingHints(hintsMap);
if(DefaultWebMapService.useStreamingRenderer())
renderer = new StreamingRenderer();
else
renderer = new ShapefileRenderer();
renderer.setContext(mapContext);
renderer.setJava2DHints(hints);
// setup the renderer hints
Map<Object, Object> rendererParams = new HashMap<Object, Object>();
rendererParams.put("optimizedDataLoadingEnabled", new Boolean(true));
rendererParams.put("renderingBuffer", new Integer(mapContext
.getBuffer()));
rendererParams.put("maxFiltersToSendToDatastore", DefaultWebMapService.getMaxFilterRules());
rendererParams.put(ShapefileRenderer.SCALE_COMPUTATION_METHOD_KEY,
ShapefileRenderer.SCALE_OGC);
if(AA_NONE.equals(antialias)) {
rendererParams.put(ShapefileRenderer.TEXT_RENDERING_KEY,
ShapefileRenderer.TEXT_RENDERING_STRING);
} else {
rendererParams.put(ShapefileRenderer.TEXT_RENDERING_KEY,
ShapefileRenderer.TEXT_RENDERING_OUTLINE);
}
if(DefaultWebMapService.isLineWidthOptimizationEnabled()) {
rendererParams.put(StreamingRenderer.LINE_WIDTH_OPTIMIZATION_KEY, true);
}
if(DefaultWebMapService.isAdvancedProjectionHandlingEnabled()) {
rendererParams.put(StreamingRenderer.ADVANCED_PROJECTION_HANDLING_KEY, true);
}
boolean kmplacemark = false;
if (mapContext.getRequest().getFormatOptions().get("kmplacemark") != null)
kmplacemark = ((Boolean) mapContext.getRequest().getFormatOptions()
.get("kmplacemark")).booleanValue();
if (kmplacemark) {
// create a StyleVisitor that copies a style, but removes the
// PointSymbolizers and TextSymbolizers
KMLStyleFilteringVisitor dupVisitor = new KMLStyleFilteringVisitor();
// Remove PointSymbolizers and TextSymbolizers from the
// layers' Styles to prevent their rendering on the
// raster image. Both are better served with the
// placemarks.
MapLayer[] layers = mapContext.getLayers();
for (int i = 0; i < layers.length; i++) {
Style style = layers[i].getStyle();
style.accept(dupVisitor);
Style copy = (Style) dupVisitor.getCopy();
layers[i].setStyle(copy);
}
}
renderer.setRendererHints(rendererParams);
// if abort already requested bail out
if (this.abortRequested) {
graphic.dispose();
return;
}
// enforce no more than x rendering errors
int maxErrors = wms.getMaxRenderingErrors();
MaxErrorEnforcer errorChecker = new MaxErrorEnforcer(renderer, maxErrors);
// Add a render listener that ignores well known rendering exceptions and reports back non
// ignorable ones
final RenderExceptionStrategy nonIgnorableExceptionListener;
nonIgnorableExceptionListener = new RenderExceptionStrategy(renderer);
renderer.addRenderListener(nonIgnorableExceptionListener);
// setup the timeout enforcer (the enforcer is neutral when the timeout is 0)
int maxRenderingTime = wms.getMaxRenderingTime() * 1000;
RenderingTimeoutEnforcer timeout = new RenderingTimeoutEnforcer(maxRenderingTime, renderer,
graphic);
timeout.start();
try {
// finally render the image;
renderer.paint(graphic, paintArea, getRenderingArea(), getRenderingTransform());
// apply watermarking
try {
if (layout != null)
this.layout.paint(graphic, paintArea, mapContext);
} catch (Exception e) {
throw new WmsException("Problem occurred while trying to watermark data", "", e);
}
} finally {
timeout.stop();
graphic.dispose();
}
// check if the request did timeout
if (timeout.isTimedOut()) {
throw new WmsException(
"This requested used more time than allowed and has been forcefully stopped. "
+ "Max rendering time is " + (maxRenderingTime / 1000.0) + "s");
}
//check if a non ignorable error occurred
if(nonIgnorableExceptionListener.exceptionOccurred()){
Exception renderError = nonIgnorableExceptionListener.getException();
throw new WmsException("Rendering process failed", "internalError", renderError);
}
// check if too many errors occurred
if(errorChecker.exceedsMaxErrors()) {
throw new WmsException("More than " + maxErrors + " rendering errors occurred, bailing out.",
"internalError", errorChecker.getLastException());
}
if (!this.abortRequested) {
if(palette != null && palette.getMapSize() < 256)