Package org.geoserver.wms.decoration

Source Code of org.geoserver.wms.decoration.TextDecoration

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.decoration;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.wms.WMSMapContent;
import org.geotools.geometry.jts.TransformedShape;
import org.geotools.renderer.style.FontCache;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.StringModel;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;

/**
* A map decoration showing a text message driven by a Freemarker template
*
* @author Andrea Aime - GeoSolutions
*/
public class TextDecoration implements MapDecoration {

    /** A logger for this class. */
    private static final Logger LOGGER = org.geotools.util.logging.Logging
            .getLogger("org.geoserver.wms.responses");
   
    private static Font DEFAULT_FONT = new java.awt.Font("Serif", java.awt.Font.PLAIN, 12);

    String fontFamily;

    boolean fontBold;

    boolean fontItalic;

    float fontSize;

    float haloRadius;

    Color haloColor;

    String messageTemplate;

    Color fontColor;

    @Override
    public void loadOptions(Map<String, String> options) throws Exception {
        // message
        this.messageTemplate = options.get("message");
        if(messageTemplate == null) {
            messageTemplate = "You forgot to set the 'message' option";
        }
        // font
        this.fontFamily = options.get("font-family");
        if (options.get("font-italic") != null) {
            this.fontItalic = Boolean.parseBoolean(options.get("font-italic"));
        }
        if (options.get("font-bold") != null) {
            this.fontBold = Boolean.parseBoolean(options.get("font-bold"));
        }
        if (options.get("font-size") != null) {
            try {
                this.fontSize = Float.parseFloat(options.get("font-size"));
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "'font-size' must be a float.", e);
            }
        }
        if (options.get("font-color") != null) {
            try {
                this.fontColor = MapDecorationLayout.parseColor(options.get("font-color"));
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "'font-color' must be a color in #RRGGBB[AA] format.", e);
            }
        }
        if(fontColor == null) {
            fontColor = Color.BLACK;
        }
        // halo
        if (options.get("halo-radius") != null) {
            try {
                this.haloRadius = Float.parseFloat(options.get("halo-radius"));
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "'halo-radius' must be a float.", e);
            }
        }
        if (options.get("halo-color") != null) {
            try {
                this.haloColor = MapDecorationLayout.parseColor(options.get("halo-color"));
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "'halo-color' must be a color in #RRGGBB[AA] format.", e);
            }
        }
        if(haloRadius > 0 && haloColor == null) {
            haloColor = Color.WHITE;
        }
    }
   
    Font getFont() {
        Font font = DEFAULT_FONT;
        if(fontFamily != null) {
            font = FontCache.getDefaultInstance().getFont(fontFamily);
            if(font == null) {
                LOGGER.log(Level.WARNING, "Font " + fontFamily + " not found, falling back on the default");
                font = DEFAULT_FONT;
            }
        }
        if(fontSize > 0) {
            font = font.deriveFont(fontSize);
        }
        if(fontItalic) {
            font = font.deriveFont(Font.ITALIC);
        }
        if(fontBold) {
            font = font.deriveFont(Font.BOLD);
        }
        return font;
    }
   
    String evaluateMessage(WMSMapContent content) throws IOException, TemplateException {
        final Map env = content.getRequest().getEnv();
        Template t = new Template("name", new StringReader(messageTemplate),
                new Configuration());
        final BeansWrapper bw = new BeansWrapper();
        return FreeMarkerTemplateUtils.processTemplateIntoString(t, new TemplateHashModel() {
           
            @Override
            public boolean isEmpty() throws TemplateModelException {
                return env.isEmpty();
            }
           
            @Override
            public TemplateModel get(String key) throws TemplateModelException {
                String value = (String) env.get(key);
                if(value != null) {
                    return new StringModel(value, bw);
                } else {
                    return null;
                }
            }
        });
    }

    @Override
    public Dimension findOptimalSize(Graphics2D g2d, WMSMapContent mapContent) throws Exception {
        Font font = getFont();
        String message = evaluateMessage(mapContent);
        GlyphVector gv = font.createGlyphVector(g2d.getFontRenderContext(), message.toCharArray());
        Shape outline = gv.getOutline();
        Rectangle2D bounds = outline.getBounds2D();
        double width = bounds.getWidth() + haloRadius * 2;
        double height = bounds.getHeight() + haloRadius * 2;
        return new Dimension((int) Math.ceil(width), (int) Math.ceil(height));
    }

    @Override
    public void paint(Graphics2D g2d, Rectangle paintArea, WMSMapContent mapContent) throws Exception {
        Font font = getFont();
        String message = evaluateMessage(mapContent);
        Font oldFont = g2d.getFont();
        Color oldColor = g2d.getColor();
        Stroke oldStroke = g2d.getStroke();
        try {
            // extract the glyph vector outline (paint like the labelling system does)
            GlyphVector gv = font.createGlyphVector(g2d.getFontRenderContext(), message.toCharArray());
            AffineTransform at = AffineTransform.getTranslateInstance(paintArea.x + haloRadius,
                    paintArea.y + paintArea.height - haloRadius);
            Shape outline = gv.getOutline();
            outline = at.createTransformedShape(outline);
           
            // draw the halo if necessary
            if(haloRadius > 0) {
                g2d.setColor(haloColor);
                g2d.setStroke(new BasicStroke(2 * haloRadius, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g2d.draw(outline);
            }
           
            // draw the string
            g2d.setFont(font);
            g2d.setColor(fontColor);
            g2d.fill(outline);
        } finally {
            g2d.setColor(oldColor);
            g2d.setFont(oldFont);
            g2d.setStroke(oldStroke);
        }
    }

}
TOP

Related Classes of org.geoserver.wms.decoration.TextDecoration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.