All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotools.styling.StrokeImpl Maven / Gradle / Ivy

Go to download

The main module contains the GeoTools public interfaces that are used by other GeoTools modules (and GeoTools applications). Where possible we make use industry standard terms as provided by OGC and ISO standards. The formal GeoTools public api consists of gt-metadata, jts and the gt-main module. The main module contains the default implementations that are available provided to other GeoTools modules using our factory system. Factories are obtained from an appropriate FactoryFinder, giving applications a chance configure the factory used using the Factory Hints facilities. FilterFactory ff = CommonFactoryFinder.getFilterFactory(); Expression expr = ff.add( expression1, expression2 ); If you find yourself using implementation specific classes chances are you doing it wrong: Expression expr = new AddImpl( expression1, expressiom2 );

There is a newer version: 24.2-oss84-1
Show newest version
/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2002-2015, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package org.geotools.styling;

import java.util.ArrayList;
import java.util.List;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.util.Utilities;
import org.geotools.util.factory.GeoTools;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.style.StyleVisitor;
import org.opengis.util.Cloneable;

/**
 * Provides a Java representation of the Stroke object in an SLD document. A stroke defines how a
 * line is rendered.
 *
 * @author James Macgill, CCG
 * @version $Id$
 */
public class StrokeImpl implements Stroke, Cloneable {
    private FilterFactory filterFactory;
    private Expression color;
    private List dashArray;
    private Expression dashOffset;
    private GraphicImpl fillGraphic;
    private GraphicImpl strokeGraphic;
    private Expression lineCap;
    private Expression lineJoin;
    private Expression opacity;
    private Expression width;

    /** Creates a new instance of Stroke */
    protected StrokeImpl() {
        this(CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints()));
    }

    protected StrokeImpl(FilterFactory factory) {
        filterFactory = factory;
    }

    public void setFilterFactory(FilterFactory factory) {
        filterFactory = factory;
    }

    /**
     * This parameter gives the solid color that will be used for a stroke.
* The color value is RGB-encoded using two hexidecimal digits per primary-color component in * the order Red, Green, Blue, prefixed with the hash (#) sign. The hexidecimal digits between A * and F may be in either upper or lower case. For example, full red is encoded as "#ff0000" * (with no quotation marks). The default color is defined to be black ("#000000"). Note: in CSS * this parameter is just called Stroke and not Color. * * @return The color of the stroke encoded as a hexidecimal RGB value. */ public Expression getColor() { return color; } /** * This parameter sets the solid color that will be used for a stroke.
* The color value is RGB-encoded using two hexidecimal digits per primary-color component in * the order Red, Green, Blue, prefixed with the hash (#) sign. The hexidecimal digits between A * and F may be in either upper or lower case. For example, full red is encoded as "#ff0000" * (with no quotation marks). The default color is defined to be black ("#000000"). Note: in CSS * this parameter is just called Stroke and not Color. * * @param color The color of the stroke encoded as a hexidecimal RGB value. This must not be * null. */ public void setColor(Expression color) { if (this.color == color) { return; } this.color = color; } /** * This parameter sets the solid color that will be used for a stroke.
* The color value is RGB-encoded using two hexidecimal digits per primary-color component in * the order Red, Green, Blue, prefixed with the hash (#) sign. The hexidecimal digits between A * and F may be in either upper or lower case. For example, full red is encoded as "#ff0000" * (with no quotation marks). The default color is defined to be black ("#000000"). Note: in CSS * this parameter is just called Stroke and not Color. * * @param color The color of the stroke encoded as a hexidecimal RGB value. */ public void setColor(String color) { setColor(filterFactory.literal(color)); } /** * Shortcut to retrieve dash array in the case where all expressions are literal numbers. Return * the default value if one of the expressions is not a literal. */ public float[] getDashArray() { if (dashArray == null) { return Stroke.DEFAULT.getDashArray(); } float[] values = new float[dashArray.size()]; int index = 0; for (Expression expression : dashArray) { if (expression instanceof Literal) { Literal literal = (Literal) expression; values[index] = literal.evaluate(null, Float.class); } else { throw new RuntimeException("Dash array is not literal: '" + expression + "'."); } index++; } return values; } /** Shortcut to define dash array using literal numbers. */ public void setDashArray(float[] literalDashArray) { if (literalDashArray != null) { dashArray = new ArrayList<>(literalDashArray.length); for (float value : literalDashArray) { dashArray.add(filterFactory.literal(value)); } } } /** * This parameter encodes the dash pattern as a list of expressions.
* The first expression gives the length in pixels of the dash to draw, the second gives the * amount of space to leave, and this pattern repeats.
* If an odd number of values is given, then the pattern is expanded by repeating it twice to * give an even number of values. * *

For example, "2 1 3 2" would produce:
* -- ---  -- ---  -- ---   * -- ---  -- ---  -- */ public List dashArray() { if (dashArray == null) { return Stroke.DEFAULT.dashArray(); } return dashArray; } /** * This parameter encodes the dash pattern as a list of expressions.
* The first expression gives the length in pixels of the dash to draw, the second gives the * amount of space to leave, and this pattern repeats.
* If an odd number of values is given, then the pattern is expanded by repeating it twice to * give an even number of values. * *

For example, "2 1 3 2" would produce:
* -- ---  -- ---  -- ---   * -- ---  -- ---  -- */ public void setDashArray(List dashArray) { this.dashArray = dashArray; } /** * This param determines where the dash pattern should start from. * * @return where the dash should start from. */ public Expression getDashOffset() { if (dashOffset == null) { return Stroke.DEFAULT.getDashOffset(); } return dashOffset; } /** * This param determines where the dash pattern should start from. * * @param dashOffset The distance into the dash pattern that should act as the start. */ public void setDashOffset(Expression dashOffset) { if (dashOffset == null) { return; } this.dashOffset = dashOffset; } /** * This parameter indicates that a stipple-fill repeated graphic will be used and specifies the * fill graphic to use. * * @return The graphic to use as a stipple fill. If null, then no Stipple fill should be used. */ public GraphicImpl getGraphicFill() { return fillGraphic; } /** * This parameter indicates that a stipple-fill repeated graphic will be used and specifies the * fill graphic to use. * * @param fillGraphic The graphic to use as a stipple fill. If null, then no Stipple fill should * be used. */ public void setGraphicFill(org.opengis.style.Graphic fillGraphic) { if (this.fillGraphic == fillGraphic) { return; } this.fillGraphic = GraphicImpl.cast(fillGraphic); } /** * This parameter indicates that a repeated-linear-graphic graphic stroke type will be used and * specifies the graphic to use. Proper stroking with a linear graphic requires two "hot-spot" * points within the space of the graphic to indicate where the rendering line starts and stops. * In the case of raster images with no special mark-up, this line will be assumed to be the * middle pixel row of the image, starting from the first pixel column and ending at the last * pixel column. * * @return The graphic to use as a linear graphic. If null, then no graphic stroke should be * used. */ public GraphicImpl getGraphicStroke() { return strokeGraphic; } /** * This parameter indicates that a repeated-linear-graphic graphic stroke type will be used and * specifies the graphic to use. Proper stroking with a linear graphic requires two "hot-spot" * points within the space of the graphic to indicate where the rendering line starts and stops. * In the case of raster images with no special mark-up, this line will be assumed to be the * middle pixel row of the image, starting from the first pixel column and ending at the last * pixel column. * * @param strokeGraphic The graphic to use as a linear graphic. If null, then no graphic stroke * should be used. */ public void setGraphicStroke(org.opengis.style.Graphic strokeGraphic) { if (this.strokeGraphic == strokeGraphic) { return; } this.strokeGraphic = GraphicImpl.cast(strokeGraphic); } /** * This parameter controls how line strings should be capped. * * @return The cap style. This will be one of "butt", "round" and "square" There is no defined * default. */ public Expression getLineCap() { if (lineCap == null) { // ConstantExpression.constant("miter") return Stroke.DEFAULT.getLineCap(); } return lineCap; } /** * This parameter controls how line strings should be capped. * * @param lineCap The cap style. This can be one of "butt", "round" and "square" There is no * defined default. */ public void setLineCap(Expression lineCap) { if (lineCap == null) { return; } this.lineCap = lineCap; } /** * This parameter controls how line strings should be joined together. * * @return The join style. This will be one of "mitre", "round" and "bevel". There is no defined * default. */ public Expression getLineJoin() { if (lineCap == null) { // ConstantExpression.constant("miter") return Stroke.DEFAULT.getLineJoin(); } return lineJoin; } /** * This parameter controls how line strings should be joined together. * * @param lineJoin The join style. This will be one of "mitre", "round" and "bevel". There is no * defined default. */ public void setLineJoin(Expression lineJoin) { if (lineJoin == null) { return; } this.lineJoin = lineJoin; } /** * This specifies the level of translucency to use when rendering the stroke.
* The value is encoded as a floating-point value between 0.0 and 1.0 with 0.0 representing * totally transparent and 1.0 representing totally opaque. A linear scale of translucency is * used for intermediate values.
* For example, "0.65" would represent 65% opacity. The default value is 1.0 (opaque). * * @return The opacity of the stroke, where 0.0 is completely transparent and 1.0 is completely * opaque. */ public Expression getOpacity() { if (lineCap == null) { return Stroke.DEFAULT.getOpacity(); } return opacity; } /** * This specifies the level of translucency to use when rendering the stroke.
* The value is encoded as a floating-point value between 0.0 and 1.0 with 0.0 representing * totally transparent and 1.0 representing totally opaque. A linear scale of translucency is * used for intermediate values.
* For example, "0.65" would represent 65% opacity. The default value is 1.0 (opaque). * * @param opacity The opacity of the stroke, where 0.0 is completely transparent and 1.0 is * completely opaque. */ public void setOpacity(Expression opacity) { if (opacity == null) { return; } this.opacity = opacity; } /** * This parameter gives the absolute width (thickness) of a stroke in pixels encoded as a float. * The default is 1.0. Fractional numbers are allowed but negative numbers are not. * * @return The width of the stroke in pixels. This may be fractional but not negative. */ public Expression getWidth() { if (width == null) { return filterFactory.literal(1.0); } return width; } /** * This parameter sets the absolute width (thickness) of a stroke in pixels encoded as a float. * The default is 1.0. Fractional numbers are allowed but negative numbers are not. * * @param width The width of the stroke in pixels. This may be fractional but not negative. */ public void setWidth(Expression width) { this.width = width; } public String toString() { StringBuffer out = new StringBuffer("org.geotools.styling.StrokeImpl:\n"); out.append("\tColor " + this.color + "\n"); out.append("\tWidth " + this.width + "\n"); out.append("\tOpacity " + this.opacity + "\n"); out.append("\tLineCap " + this.lineCap + "\n"); out.append("\tLineJoin " + this.lineJoin + "\n"); out.append("\tDash Array " + this.dashArray + "\n"); out.append("\tDash Offset " + this.dashOffset + "\n"); out.append("\tFill Graphic " + this.fillGraphic + "\n"); out.append("\tStroke Graphic " + this.strokeGraphic); return out.toString(); } public java.awt.Color getColor(SimpleFeature feature) { return java.awt.Color.decode((String) this.getColor().evaluate(feature)); } public Object accept(StyleVisitor visitor, Object data) { return visitor.visit(this, data); } public void accept(org.geotools.styling.StyleVisitor visitor) { visitor.visit(this); } /** * Clone the StrokeImpl object. * *

The clone is a deep copy of the original, except for the expression values which are * immutable. * * @see org.geotools.styling.Stroke#clone() */ public Object clone() { try { StrokeImpl clone = (StrokeImpl) super.clone(); if (dashArray != null) { clone.setDashArray((new ArrayList(dashArray))); } if (fillGraphic != null && fillGraphic instanceof Cloneable) { clone.fillGraphic = (GraphicImpl) ((Cloneable) fillGraphic).clone(); } if (strokeGraphic != null && fillGraphic instanceof Cloneable) { clone.strokeGraphic = (GraphicImpl) ((Cloneable) strokeGraphic).clone(); } return clone; } catch (CloneNotSupportedException e) { // This will never happen throw new RuntimeException("Failed to clone StrokeImpl"); } } public int hashCode() { final int PRIME = 1000003; int result = 0; if (color != null) { result = (PRIME * result) + color.hashCode(); } if (dashOffset != null) { result = (PRIME * result) + dashOffset.hashCode(); } if (fillGraphic != null) { result = (PRIME * result) + fillGraphic.hashCode(); } if (strokeGraphic != null) { result = (PRIME * result) + strokeGraphic.hashCode(); } if (lineCap != null) { result = (PRIME * result) + lineCap.hashCode(); } if (lineJoin != null) { result = (PRIME * result) + lineJoin.hashCode(); } if (opacity != null) { result = (PRIME * result) + opacity.hashCode(); } if (width != null) { result = (PRIME * result) + width.hashCode(); } if (dashArray != null) { result = (PRIME * result) + dashArray.hashCode(); } return result; } /** * Compares this stroke with another stroke for equality. * * @param oth The other StrokeImpl to compare * @return True if this and oth are equal. */ public boolean equals(Object oth) { if (this == oth) { return true; } if (oth == null) { return false; } if (oth.getClass() != getClass()) { return false; } StrokeImpl other = (StrokeImpl) oth; // check the color first - most likely to change if (!Utilities.equals(getColor(), other.getColor())) { return false; } // check the width if (!Utilities.equals(getWidth(), other.getWidth())) { return false; } if (!Utilities.equals(getLineCap(), other.getLineCap())) { return false; } if (!Utilities.equals(getLineJoin(), other.getLineJoin())) { return false; } if (!Utilities.equals(getOpacity(), other.getOpacity())) { return false; } if (!Utilities.equals(getGraphicFill(), other.getGraphicFill())) { return false; } if (!Utilities.equals(getGraphicStroke(), other.getGraphicStroke())) { return false; } if (!Utilities.equals(dashArray(), other.dashArray())) { return false; } return true; } static StrokeImpl cast(org.opengis.style.Stroke stroke) { if (stroke == null) { return null; } else if (stroke instanceof StrokeImpl) { return (StrokeImpl) stroke; } else { StrokeImpl copy = new StrokeImpl(); copy.setColor(stroke.getColor()); copy.setDashArray(stroke.getDashArray()); copy.setDashOffset(stroke.getDashOffset()); copy.setGraphicFill(GraphicImpl.cast(stroke.getGraphicFill())); copy.setGraphicStroke(GraphicImpl.cast(stroke.getGraphicStroke())); copy.setLineCap(stroke.getLineCap()); copy.setLineJoin(stroke.getLineJoin()); copy.setOpacity(stroke.getOpacity()); copy.setWidth(stroke.getWidth()); return copy; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy