blob: 40b2e80edefd6e8b3e1e54875aca1513bdb804a8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.style.se1;
import java.net.URI;
import java.awt.Color;
import java.util.Objects;
import org.apache.sis.feature.privy.AttributeConvention;
import org.apache.sis.metadata.iso.citation.DefaultOnlineResource;
// Specific to the main branch:
import org.apache.sis.filter.Expression;
import org.apache.sis.filter.DefaultFilterFactory;
/**
* Factory of style elements.
* Style factory uses a {@link FilterFactory} instance that depends on the type of data to be styled.
* That type of data is specified by the parameterized type {@code <R>}.
* The two main types are {@link org.apache.sis.feature.AbstractFeature}
* and {@link org.apache.sis.coverage.BandedCoverage}.
*
* @author Martin Desruisseaux (Geomatys)
*
* @param <R> the type of data to style, such as {@code Feature} or {@code Coverage}.
*/
public class StyleFactory<R> {
/**
* The factory to use for creating expressions.
*/
final DefaultFilterFactory<R,?,?> filterFactory;
/**
* Literal commonly used as a default value.
*
* @see StyleElement#defaultToTrue(Expression)
* @see StyleElement#defaultToFalse(Expression)
*/
final Expression<R,Boolean> enabled, disabled;
/**
* Literal commonly used as a default value.
*/
final Expression<R,Integer> zeroAsInt;
/**
* Literal commonly used as a default value.
*
* @see StyleElement#defaultToZero(Expression)
* @see StyleElement#defaultToHalf(Expression)
* @see StyleElement#defaultToOne(Expression)
*/
final Expression<R,Double> zero, half, one, six, ten;
/**
* Default factor for shaded relief.
* This is an arbitrary suggested but not standardized by OGC 05-077r4.
*/
final Expression<R,Double> relief;
/**
* Literal commonly used as a default value.
*/
final Expression<R,String> normal, square, bevel;
/**
* Literal for a predefined color which can be used as fill color.
*/
final Expression<R,Color> black, gray, white;
/**
* An expression for fetching the default geometry.
*
* @todo According SE specification, the default expression in the context of some symbolizers should
* fetch all geometries, not only a default one. The default seems to depend on the symbolizer type.
*/
final Expression<R,?> defaultGeometry;
/**
* Creates a new style factory.
*
* @param filterFactory the factory to use for creating expressions.
*/
public StyleFactory(final DefaultFilterFactory<R,?,?> filterFactory) {
this.filterFactory = Objects.requireNonNull(filterFactory);
enabled = filterFactory.literal(Boolean.TRUE);
disabled = filterFactory.literal(Boolean.FALSE);
zeroAsInt = filterFactory.literal(0);
zero = filterFactory.literal(0.0);
half = filterFactory.literal(0.5);
one = filterFactory.literal(1.0);
six = filterFactory.literal(6.0);
ten = filterFactory.literal(10.0);
relief = filterFactory.literal(55.0);
normal = filterFactory.literal("normal");
square = filterFactory.literal("square");
bevel = filterFactory.literal("bevel");
black = filterFactory.literal(Color.BLACK);
gray = filterFactory.literal(Color.GRAY);
white = filterFactory.literal(Color.WHITE);
defaultGeometry = filterFactory.property(AttributeConvention.GEOMETRY);
}
/**
* Creates a new style factory with the same literals as the given factory.
* This constructor shall not be public because it assumes that all literals
* are implementations that ignore the type {@code <R>} of data to style,
* in which case the unchecked cast is safe.
*
* @param source the style factory to copy.
*/
@SuppressWarnings("unchecked")
StyleFactory(final StyleFactory<?> source) {
enabled = (Expression<R,Boolean>) source.enabled;
disabled = (Expression<R,Boolean>) source.disabled;
zeroAsInt = (Expression<R,Integer>) source.zeroAsInt;
zero = (Expression<R,Double>) source.zero;
half = (Expression<R,Double>) source.half;
one = (Expression<R,Double>) source.one;
six = (Expression<R,Double>) source.six;
ten = (Expression<R,Double>) source.ten;
relief = (Expression<R,Double>) source.relief;
normal = (Expression<R,String>) source.normal;
square = (Expression<R,String>) source.square;
bevel = (Expression<R,String>) source.bevel;
black = (Expression<R,Color>) source.black;
gray = (Expression<R,Color>) source.gray;
white = (Expression<R,Color>) source.white;
filterFactory = null; // TODO: FilterFactory for coverage is not yet available.
defaultGeometry = null; // Idem.
}
/**
* Creates an initially empty rule.
* A rule is a set of tendering instructions grouped by feature-property conditions and map scales.
*
* @return new initially empty rule.
*/
public Rule<R> createRule() {
return new Rule<>(this);
}
/**
* Creates a point symbolizer initialized to a default graphic.
* A point symbolizer is a set of instructions about how to draw a graphic at a point.
*
* @return new point symbolizer initialized to a default graphic.
*/
public PointSymbolizer<R> createPointSymbolizer() {
return new PointSymbolizer<>(this);
}
/**
* Creates a line symbolizer with the default stroke and no perpendicular offset.
* A line symbolizer is a set of instructions about how to draw on a map the lines of a geometry.
*
* @return new ine symbolizer with the default stroke and no perpendicular offset.
*/
public LineSymbolizer<R> createLineSymbolizer() {
return new LineSymbolizer<>(this);
}
/**
* Creates a polygon symbolizer initialized to the default fill and default stroke.
* A polygon symbolizer is a set of instructions about how to draw on a map the lines and the interior of polygons.
*
* @return new polygon symbolizer initialized to the default fill and default stroke.
*/
public PolygonSymbolizer<R> createPolygonSymbolizer() {
return new PolygonSymbolizer<>(this);
}
/**
* Creates a text symbolizer with default placement and default font.
* A text symbolizer is a set of instructions about how to drawn text on a map.
* The new symbolizer has no initial label.
*
* @return new text symbolizer with default placement and default font.
*
* @see #createTextSymbolizer(String)
*/
public TextSymbolizer<R> createTextSymbolizer() {
return new TextSymbolizer<>(this);
}
/**
* Creates a text symbolizer initialized with the specified label literal.
*
* @param label initial label literal, or {@code null} if none.
* @return new text symbolizer with default placement and default font.
*/
public TextSymbolizer<R> createTextSymbolizer(final String label) {
final var s = createTextSymbolizer();
s.label = s.literal(label);
return s;
}
/**
* Creates an initially opaque raster symbolizer with no contrast enhancement, shaded relief or outline.
* A raster symbolizer is a set of instructions about how to render raster, matrix or coverage data.
*
* @return new initially opaque raster symbolizer.
*/
public RasterSymbolizer<R> createRasterSymbolizer() {
return new RasterSymbolizer<>(this);
}
/**
* Creates an initially empty description.
* A description is a set of human-readable information about a style object being defined.
*
* @return new initially empty description.
*/
public Description<R> createDescription() {
return new Description<>(this);
}
/**
* Creates a point placement initialized to anchor at the middle and no displacement.
* A point placement is a set of instructions about how a text label is positioned relative to a point.
*
* @return new point placement initialized to anchor at the middle and no displacement.
*/
public PointPlacement<R> createPointPlacement() {
return new PointPlacement<>(this);
}
/**
* Creates a line placement initialized to no offset, no repetition and no gap.
* A line placement is a set of instructions about where and how a text label should be rendered relative to a line.
*
* @return new line placement initialized to no offset, no repetition and no gap.
*/
public LinePlacement<R> createLinePlacement() {
return new LinePlacement<>(this);
}
/**
* Creates an anchor point initialized to <var>x</var> = 0.5 and <var>y</var> = 0.5.
* An anchor point is the location inside a graphic or label to use as an "anchor"
* for positioning it relative to a point.
*
* @return new anchor point initialized to center.
*
* @see #createAnchorPoint(double, double)
*/
public AnchorPoint<R> createAnchorPoint() {
return new AnchorPoint<>(this);
}
/**
* Creates an anchor point initialized to the given position.
* This is a convenience method for a frequently used operation.
*
* @param x the initial <var>x</var> position.
* @param y the initial <var>y</var> position.
* @return new anchor point initialized to the given position.
*/
public AnchorPoint<R> createAnchorPoint(final double x, final double y) {
final var s = createAnchorPoint();
s.anchorPointX = filterFactory.literal(x);
s.anchorPointY = filterFactory.literal(y);
return s;
}
/**
* Creates a displacement initialized to zero offsets.
* A displacement is the two-dimensional offsets from the original geometry.
*
* @return new displacement initialized to zero offsets.
*
* @see #createDisplacement(double, double)
*/
public Displacement<R> createDisplacement() {
return new Displacement<>(this);
}
/**
* Creates a displacement initialized to the given offsets.
* This is a convenience method for a frequently used operation.
*
* @param x the <var>x</var> displacement.
* @param y the <var>y</var> displacement.
* @return new displacement initialized to the given offsets.
*/
public Displacement<R> createDisplacement(final double x, final double y) {
final var s = createDisplacement();
s.displacementX = filterFactory.literal(x);
s.displacementY = filterFactory.literal(y);
return s;
}
/**
* Creates a mark initialized to a gray square with black outline.
* A mark is a predefined shape that can be drawn at the points of the geometry.
*
* @return new mark initialized to a gray square with black outline.
*/
public Mark<R> createMark() {
return new Mark<>(this);
}
/**
* Creates an initially empty external graphic.
* An external graphic is a reference to an external file that contains an image of some kind,
* such as a PNG or SVG.
*
* @return new initially empty external graphic.
*
* @see #createExternalGraphic(URI, String)
*/
public ExternalGraphic<R> createExternalGraphic() {
return new ExternalGraphic<>(this);
}
/**
* Creates an external graphic initialized to the given URI.
*
* @param linkage URI to the external graphic, or {@code null} if none.
* @param format MIME type of the external graphic, or {@code null} if unspecified.
* @return new external graphic initialized to the given URI.
*/
public ExternalGraphic<R> createExternalGraphic(final URI linkage, final String format) {
final var s = createExternalGraphic();
s.format = format;
if (linkage != null) {
s.onlineResource = new DefaultOnlineResource(linkage);
}
return s;
}
/**
* Creates a stroke initialized to solid line of black opaque color, 1 pixel width.
* A stroke is a set of instructions about how to draw styled lines.
*
* @return new stroke initialized to solid line of black opaque color, 1 pixel width.
*
* @see #createStroke(Color)
*/
public Stroke<R> createStroke() {
return new Stroke<>(this);
}
/**
* Creates a stroke initialized to the given color and opacity.
* The alpha channel of the given color is used for determining the opacity.
*
* @param color the initial color, or {@code null} if none.
* @return new stroke initialized to the given color and opacity.
*/
public Stroke<R> createStroke(final Color color) {
final var s = createStroke();
s.setColorAndOpacity(color);
return s;
}
/**
* Creates an opaque fill initialized to the gray color.
* A fill is a set of instructions about how to fill the interior of polygons.
*
* @return new opaque fill initialized to the gray color.
*
* @see #createFill(Color)
*/
public Fill<R> createFill() {
return new Fill<>(this);
}
/**
* Creates a fill initialized to the given color and opacity.
* The alpha channel of the given color is used for determining the opacity.
*
* @param color the initial color, or {@code null} if none.
* @return new fill initialized to the given color and opacity.
*/
public Fill<R> createFill(final Color color) {
final var s = createFill();
s.setColorAndOpacity(color);
return s;
}
/**
* Creates an halo initialized to a white color and a radius of 1 pixel.
* A halo is a fill that are applied to the backgrounds of font glyphs.
*
* @return new halo initialized to a white color and a radius of 1 pixel.
*/
public Halo<R> createHalo() {
return new Halo<>(this);
}
/**
* Creates a font initialized to normal style, normal weight and a size of 10 pixels.
* A font is the identification of a font of a certain family, style, and size.
*
* @return new font initialized to normal style, normal weight and a size of 10 pixels.
*/
public Font<R> createFont() {
return new Font<>(this);
}
/**
* Creates a graphic initialized to opaque default mark, default size and no rotation.
* A graphic is a symbol with an inherent shape, color(s), and possibly size.
*
* @return new graphic initialized to opaque default mark, default size and no rotation.
*/
public Graphic<R> createGraphic() {
return new Graphic<>(this);
}
/**
* Creates a graphic fill initialized to a default graphic.
* A graphic fill is a stipple-fill repeated graphic.
*
* @return new graphic fill initialized to a default graphic.
*/
public GraphicFill<R> createGraphicFill() {
return new GraphicFill<>(this);
}
/**
* Creates a graphic stroke initialized to a default graphic and no gap.
* A graphic stroke is a repeated-linear-graphic stroke.
*
* @return new graphic stroke initialized to a default graphic and no gap.
*/
public GraphicStroke<R> createGraphicStroke() {
return new GraphicStroke<>(this);
}
/**
* Creates a legend initialized to the default graphic.
* A legend graphic is a graphic to do displayed in a legend for a rule.
*
* @return new legend initialized to the default graphic.
*/
public LegendGraphic<R> createLegendGraphic() {
return new LegendGraphic<>(this);
}
/**
* Creates an initially empty color replacement.
* A color replacement defines the replacement of a color in an external graphic.
*
* @return new initially empty color replacement.
*/
public ColorReplacement<R> createColorReplacement() {
return new ColorReplacement<>(this);
}
/**
* Creates an initially empty color map.
* A color map is the mapping of fixed-numeric pixel values to colors.
*
* @return new initially empty color map.
*/
public ColorMap<R> createColorMap() {
return new ColorMap<>(this);
}
/**
* Creates an initially empty channel selection.
* A channel selection specifies the false-color channel selection for a multi-spectral raster source.
*
* @return new initially empty channel selection.
*/
public ChannelSelection<R> createChannelSelection() {
return new ChannelSelection<>(this);
}
/**
* Creates an initially empty selected channel.
* A selected channel is information about a channel to use in a multi-spectral source.
*
* @return new initially empty selected channel.
*
* @see #createSelectedChannel(String)
*/
public SelectedChannel<R> createSelectedChannel() {
return new SelectedChannel<>(this);
}
/**
* Creates a selected channel initialized to the given channel name.
*
* @param sourceChannelName the channel's name, or {@code null} if unspecified.
* @return new selected channel for the given name.
*/
public SelectedChannel<R> createSelectedChannel(final String sourceChannelName) {
final var s = createSelectedChannel();
s.sourceChannelName = s.literal(sourceChannelName);
return s;
}
/**
* Creates a contrast enhancement initialized to no operation.
*
* @return new contrast enhancement initialized to no operation.
*/
public ContrastEnhancement<R> createContrastEnhancement() {
return new ContrastEnhancement<> (this);
}
/**
* Creates a shaded relief initialized to implementation-specific default values.
* A shaded relief is a “hill shading” applied to an image for a three-dimensional visual effect.
*
* @return new shaded relief initialized to implementation-specific default values.
*/
public ShadedRelief<R> createShadedRelief() {
return new ShadedRelief<>(this);
}
}