source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextLabel.java@ 12476

Last change on this file since 12476 was 12476, checked in by michael2402, 7 years ago

Fix #15006: Separate offset handling for ways, areas and node. Handle offset for all three of them.

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.styleelement;
3
4import java.awt.Color;
5import java.awt.Font;
6import java.awt.geom.Point2D;
7import java.util.Objects;
8
9import org.openstreetmap.josm.data.osm.OsmPrimitive;
10import org.openstreetmap.josm.gui.mappaint.Cascade;
11import org.openstreetmap.josm.gui.mappaint.Environment;
12import org.openstreetmap.josm.gui.mappaint.Keyword;
13import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.TagKeyReference;
14import org.openstreetmap.josm.gui.mappaint.StyleKeys;
15import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy;
16import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.StaticLabelCompositionStrategy;
17import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.TagLookupCompositionStrategy;
18import org.openstreetmap.josm.tools.CheckParameterUtil;
19import org.openstreetmap.josm.tools.Utils;
20
21/**
22 * Represents the rendering style for a textual label placed somewhere on the map.
23 * @since 3880
24 */
25public class TextLabel implements StyleKeys {
26 /**
27 * The default strategy to use when determining the label of a element.
28 */
29 public static final LabelCompositionStrategy AUTO_LABEL_COMPOSITION_STRATEGY = new DeriveLabelFromNameTagsCompositionStrategy();
30
31 /**
32 * The strategy for building the actual label value for a given a {@link OsmPrimitive}.
33 * Check for null before accessing.
34 */
35 public LabelCompositionStrategy labelCompositionStrategy;
36 /**
37 * the font to be used when rendering
38 */
39 public Font font;
40 /**
41 * The color to draw the text in, includes alpha.
42 */
43 public Color color;
44 /**
45 * The radius of the halo effect.
46 */
47 public Float haloRadius;
48 /**
49 * The color of the halo effect.
50 */
51 public Color haloColor;
52
53 /**
54 * Creates a new text element
55 *
56 * @param strategy the strategy indicating how the text is composed for a specific {@link OsmPrimitive} to be rendered.
57 * If null, no label is rendered.
58 * @param font the font to be used. Must not be null.
59 * @param color the color to be used. Must not be null
60 * @param haloRadius halo radius
61 * @param haloColor halo color
62 */
63 protected TextLabel(LabelCompositionStrategy strategy, Font font, Color color, Float haloRadius,
64 Color haloColor) {
65 this.labelCompositionStrategy = strategy;
66 this.font = Objects.requireNonNull(font, "font");
67 this.color = Objects.requireNonNull(color, "color");
68 this.haloRadius = haloRadius;
69 this.haloColor = haloColor;
70 }
71
72 /**
73 * Copy constructor
74 *
75 * @param other the other element.
76 */
77 public TextLabel(TextLabel other) {
78 this.labelCompositionStrategy = other.labelCompositionStrategy;
79 this.font = other.font;
80 this.color = other.color;
81 this.haloColor = other.haloColor;
82 this.haloRadius = other.haloRadius;
83 }
84
85 /**
86 * Derives a suitable label composition strategy from the style properties in {@code c}.
87 *
88 * @param c the style properties
89 * @param defaultAnnotate whether to return {@link #AUTO_LABEL_COMPOSITION_STRATEGY} if not strategy is found
90 * @return the label composition strategy, or {@code null}
91 */
92 protected static LabelCompositionStrategy buildLabelCompositionStrategy(Cascade c, boolean defaultAnnotate) {
93 /*
94 * If the cascade includes a TagKeyReference we will lookup the rendered label
95 * from a tag value.
96 */
97 TagKeyReference tkr = c.get(TEXT, null, TagKeyReference.class, true);
98 if (tkr != null)
99 return new TagLookupCompositionStrategy(tkr.key);
100
101 /*
102 * Check whether the label composition strategy is given by a keyword
103 */
104 Keyword keyword = c.get(TEXT, null, Keyword.class, true);
105 if (Keyword.AUTO.equals(keyword))
106 return AUTO_LABEL_COMPOSITION_STRATEGY;
107
108 /*
109 * Do we have a static text label?
110 */
111 String text = c.get(TEXT, null, String.class, true);
112 if (text != null)
113 return new StaticLabelCompositionStrategy(text);
114 return defaultAnnotate ? AUTO_LABEL_COMPOSITION_STRATEGY : null;
115 }
116
117 /**
118 * Builds a text element from style properties in {@code c} and the
119 * default text color {@code defaultTextColor}
120 *
121 * @param env the environment
122 * @param defaultTextColor the default text color. Must not be null.
123 * @param defaultAnnotate true, if a text label shall be rendered by default, even if the style sheet
124 * doesn't include respective style declarations
125 * @return the text element or null, if the style properties don't include
126 * properties for text rendering
127 * @throws IllegalArgumentException if {@code defaultTextColor} is null
128 */
129 public static TextLabel create(Environment env, Color defaultTextColor, boolean defaultAnnotate) {
130 CheckParameterUtil.ensureParameterNotNull(defaultTextColor);
131 Cascade c = env.mc.getCascade(env.layer);
132
133 LabelCompositionStrategy strategy = buildLabelCompositionStrategy(c, defaultAnnotate);
134 if (strategy == null) return null;
135 String s = strategy.compose(env.osm);
136 if (s == null) return null;
137 Font font = StyleElement.getFont(c, s);
138
139 Color color = c.get(TEXT_COLOR, defaultTextColor, Color.class);
140 float alpha = c.get(TEXT_OPACITY, 1f, Float.class);
141 color = Utils.alphaMultiply(color, alpha);
142
143 Float haloRadius = c.get(TEXT_HALO_RADIUS, null, Float.class);
144 if (haloRadius != null && haloRadius <= 0) {
145 haloRadius = null;
146 }
147 Color haloColor = null;
148 if (haloRadius != null) {
149 haloColor = c.get(TEXT_HALO_COLOR, Utils.complement(color), Color.class);
150 float haloAlphaFactor = c.get(TEXT_HALO_OPACITY, 1f, Float.class);
151 haloColor = Utils.alphaMultiply(haloColor, haloAlphaFactor);
152 }
153
154 return new TextLabel(strategy, font, color, haloRadius, haloColor);
155 }
156
157 /**
158 * Gets the text-offset property from a cascade
159 * @param c The cascade
160 * @return The text offset property
161 */
162 public static Point2D getTextOffset(Cascade c) {
163 float xOffset = 0;
164 float yOffset = 0;
165 float[] offset = c.get(TEXT_OFFSET, null, float[].class);
166 if (offset != null) {
167 if (offset.length == 1) {
168 yOffset = offset[0];
169 } else if (offset.length >= 2) {
170 xOffset = offset[0];
171 yOffset = offset[1];
172 }
173 }
174 xOffset = c.get(TEXT_OFFSET_X, xOffset, Float.class);
175 yOffset = c.get(TEXT_OFFSET_Y, yOffset, Float.class);
176 return new Point2D.Double(xOffset, yOffset);
177 }
178
179 /**
180 * Replies the label to be rendered for the primitive {@code osm}.
181 *
182 * @param osm the OSM object
183 * @return the label, or null, if {@code osm} is null or if no label can be
184 * derived for {@code osm}
185 */
186 public String getString(OsmPrimitive osm) {
187 if (labelCompositionStrategy == null) return null;
188 return labelCompositionStrategy.compose(osm);
189 }
190
191 @Override
192 public String toString() {
193 return "TextLabel{" + toStringImpl() + '}';
194 }
195
196 protected String toStringImpl() {
197 StringBuilder sb = new StringBuilder(96);
198 sb.append("labelCompositionStrategy=").append(labelCompositionStrategy)
199 .append(" font=").append(font)
200 .append(" color=").append(Utils.toString(color));
201 if (haloRadius != null) {
202 sb.append(" haloRadius=").append(haloRadius)
203 .append(" haloColor=").append(haloColor);
204 }
205 return sb.toString();
206 }
207
208 @Override
209 public int hashCode() {
210 return Objects.hash(labelCompositionStrategy, font, color, haloRadius, haloColor);
211 }
212
213 @Override
214 public boolean equals(Object obj) {
215 if (this == obj) return true;
216 if (obj == null || getClass() != obj.getClass()) return false;
217 TextLabel textLabel = (TextLabel) obj;
218 return Objects.equals(labelCompositionStrategy, textLabel.labelCompositionStrategy) &&
219 Objects.equals(font, textLabel.font) &&
220 Objects.equals(color, textLabel.color) &&
221 Objects.equals(haloRadius, textLabel.haloRadius) &&
222 Objects.equals(haloColor, textLabel.haloColor);
223 }
224}
Note: See TracBrowser for help on using the repository browser.