The gt-render module supplies two factories that can be used to teach the rendering system about your custom icons.

Notes: This is considered Advanced material because you need to register the factory you have created.


The job of this class is to evaluate the provided expression (it should evaluate into a String) and construct a good Java Shape out of it that we can draw on the map.:

 *    GeoTools Sample code and Tutorials by Open Source Geospatial Foundation, and others
 *    https://docs.geotools.org
 *    To the extent possible under law, the author(s) have dedicated all copyright
 *    and related and neighboring rights to this software to the public domain worldwide.
 *    This software is distributed without any warranty.
 *    You should have received a copy of the CC0 Public Domain Dedication along with this
 *    software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
package org.geotools.render;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import org.geotools.api.feature.Feature;
import org.geotools.api.filter.expression.Expression;
import org.geotools.renderer.style.MarkFactory;

class SplatMarkFactory implements MarkFactory {

    private static GeneralPath SPLAT;

    static {
        SPLAT = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
        SPLAT.moveTo(-0.2f, 0.9f);
        SPLAT.lineTo(0.266f, -0.5f);
        SPLAT.lineTo(-0.366f, -0.7f);
        SPLAT.lineTo(0.4f, 1.12f);
        SPLAT.lineTo(0.3f, 1.10f);

    public Shape getShape(Graphics2D graphics, Expression symbolUrl, Feature feature)
            throws Exception {
        if (symbolUrl == null) {
            // cannot handle a null url
            return null;
        // Evaluate the expression as a String
        String wellKnownName = symbolUrl.evaluate(feature, String.class);

        if (wellKnownName != null && wellKnownName.equalsIgnoreCase("splat")) {
            return SPLAT;
        return null; // we do not know this one

To use this class we are going to need to define a style that refers to this new mark:

        StyleBuilder builder = new StyleBuilder();
        FilterFactory ff = builder.getFilterFactory();

        Graphic splat = builder.createGraphic(null, builder.createMark("splat"), null);
        PointSymbolizer symbolizer = builder.createPointSymbolizer(splat);

        // builder will fill in all the other classes with defaults
        Style style = builder.createStyle(symbolizer);

To register your class you will need to:

  1. Create the following folder: META_INF/services/

  2. In this folder create a file: org.geotools.renderer.style.MarkFactory

    The contents of this file should list your implementation:



This factory is much more capable, as it is not restricted to creating a simple shape.

This class is responsible for:

  • evaluate the provided expression (it should evaluate into a URL)

    A feature is allowing the expression to refer to attributes if needed.

  • construct a Java Icon

  • both a format and a size are provided for reference

Your implementation can:

  • implement a dynamic Icon directly (useful for symbols that need to be composed based on feature attributes)

  • or as simple as a straight SwingIcon backed by a PNG file contained in your jar.