source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java@ 7083

Last change on this file since 7083 was 7083, checked in by Don-vip, 10 years ago

see #8465 - replace Utils.equal by Objects.equals, new in Java 7

  • Property svn:eol-style set to native
File size: 14.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import java.awt.BasicStroke;
5import java.awt.Color;
6import java.util.Arrays;
7import java.util.Objects;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.data.osm.Node;
11import org.openstreetmap.josm.data.osm.OsmPrimitive;
12import org.openstreetmap.josm.data.osm.Way;
13import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
14import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
15import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
16import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
17import org.openstreetmap.josm.tools.Utils;
18
19public class LineElemStyle extends ElemStyle {
20
21 public static LineElemStyle createSimpleLineStyle(Color color, boolean isAreaEdge) {
22 MultiCascade mc = new MultiCascade();
23 Cascade c = mc.getOrCreateCascade("default");
24 c.put(WIDTH, Keyword.DEFAULT);
25 c.put(COLOR, color != null ? color : PaintColors.UNTAGGED.get());
26 if (isAreaEdge) {
27 c.put(Z_INDEX, -3f);
28 }
29 return createLine(new Environment(null, mc, "default", null));
30 }
31 public static final LineElemStyle UNTAGGED_WAY = createSimpleLineStyle(null, false);
32
33 private BasicStroke line;
34 public Color color;
35 public Color dashesBackground;
36 public float offset;
37 public float realWidth; // the real width of this line in meter
38
39 private BasicStroke dashesLine;
40
41 protected enum LineType {
42 NORMAL("", 3f),
43 CASING("casing-", 2f),
44 LEFT_CASING("left-casing-", 2.1f),
45 RIGHT_CASING("right-casing-", 2.1f);
46
47 public final String prefix;
48 public final float default_major_z_index;
49
50 LineType(String prefix, float default_major_z_index) {
51 this.prefix = prefix;
52 this.default_major_z_index = default_major_z_index;
53 }
54 }
55
56 protected LineElemStyle(Cascade c, float default_major_z_index, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, float offset, float realWidth) {
57 super(c, default_major_z_index);
58 this.line = line;
59 this.color = color;
60 this.dashesLine = dashesLine;
61 this.dashesBackground = dashesBackground;
62 this.offset = offset;
63 this.realWidth = realWidth;
64 }
65
66 public static LineElemStyle createLine(Environment env) {
67 return createImpl(env, LineType.NORMAL);
68 }
69
70 public static LineElemStyle createLeftCasing(Environment env) {
71 LineElemStyle leftCasing = createImpl(env, LineType.LEFT_CASING);
72 if (leftCasing != null) {
73 leftCasing.isModifier = true;
74 }
75 return leftCasing;
76 }
77
78 public static LineElemStyle createRightCasing(Environment env) {
79 LineElemStyle rightCasing = createImpl(env, LineType.RIGHT_CASING);
80 if (rightCasing != null) {
81 rightCasing.isModifier = true;
82 }
83 return rightCasing;
84 }
85
86 public static LineElemStyle createCasing(Environment env) {
87 LineElemStyle casing = createImpl(env, LineType.CASING);
88 if (casing != null) {
89 casing.isModifier = true;
90 }
91 return casing;
92 }
93
94 private static LineElemStyle createImpl(Environment env, LineType type) {
95 Cascade c = env.mc.getCascade(env.layer);
96 Cascade c_def = env.mc.getCascade("default");
97 Float width;
98 switch (type) {
99 case NORMAL:
100 width = getWidth(c, WIDTH, getWidth(c_def, WIDTH, null));
101 break;
102 case CASING:
103 Float casingWidth = c.get(type.prefix + WIDTH, null, Float.class, true);
104 if (casingWidth == null) {
105 RelativeFloat rel_casingWidth = c.get(type.prefix + WIDTH, null, RelativeFloat.class, true);
106 if (rel_casingWidth != null) {
107 casingWidth = rel_casingWidth.val / 2;
108 }
109 }
110 if (casingWidth == null)
111 return null;
112 width = getWidth(c, WIDTH, getWidth(c_def, WIDTH, null));
113 if (width == null) {
114 width = 0f;
115 }
116 width += 2 * casingWidth;
117 break;
118 case LEFT_CASING:
119 case RIGHT_CASING:
120 width = getWidth(c, type.prefix + WIDTH, null);
121 break;
122 default:
123 throw new AssertionError();
124 }
125 if (width == null)
126 return null;
127
128 float realWidth = c.get(type.prefix + REAL_WIDTH, 0f, Float.class);
129 if (realWidth > 0 && MapPaintSettings.INSTANCE.isUseRealWidth()) {
130
131 /* if we have a "width" tag, try use it */
132 String widthTag = env.osm.get("width");
133 if (widthTag == null) {
134 widthTag = env.osm.get("est_width");
135 }
136 if (widthTag != null) {
137 try {
138 realWidth = Float.valueOf(widthTag);
139 } catch(NumberFormatException nfe) {
140 Main.warn(nfe);
141 }
142 }
143 }
144
145 Float offset = c.get(OFFSET, 0f, Float.class);
146 switch (type) {
147 case NORMAL:
148 break;
149 case CASING:
150 offset += c.get(type.prefix + OFFSET, 0f, Float.class);
151 break;
152 case LEFT_CASING:
153 case RIGHT_CASING:
154 {
155 Float baseWidthOnDefault = getWidth(c_def, WIDTH, null);
156 Float baseWidth = getWidth(c, WIDTH, baseWidthOnDefault);
157 if (baseWidth == null || baseWidth < 2f) {
158 baseWidth = 2f;
159 }
160 float casingOffset = c.get(type.prefix + OFFSET, 0f, Float.class);
161 casingOffset += baseWidth / 2 + width / 2;
162 /* flip sign for the right-casing-offset */
163 if (type == LineType.RIGHT_CASING) {
164 casingOffset *= -1f;
165 }
166 offset += casingOffset;
167 break;
168 }
169 }
170
171 Color color = c.get(type.prefix + COLOR, null, Color.class);
172 if (type == LineType.NORMAL && color == null) {
173 color = c.get(FILL_COLOR, null, Color.class);
174 }
175 if (color == null) {
176 color = PaintColors.UNTAGGED.get();
177 }
178
179 int alpha = 255;
180 Integer pAlpha = Utils.color_float2int(c.get(type.prefix + OPACITY, null, Float.class));
181 if (pAlpha != null) {
182 alpha = pAlpha;
183 }
184 color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
185
186 float[] dashes = c.get(type.prefix + DASHES, null, float[].class, true);
187 if (dashes != null) {
188 boolean hasPositive = false;
189 for (float f : dashes) {
190 if (f > 0) {
191 hasPositive = true;
192 }
193 if (f < 0) {
194 dashes = null;
195 break;
196 }
197 }
198 if (!hasPositive || (dashes != null && dashes.length == 0)) {
199 dashes = null;
200 }
201 }
202 float dashesOffset = c.get(type.prefix + DASHES_OFFSET, 0f, Float.class);
203 Color dashesBackground = c.get(type.prefix + DASHES_BACKGROUND_COLOR, null, Color.class);
204 if (dashesBackground != null) {
205 pAlpha = Utils.color_float2int(c.get(type.prefix + DASHES_BACKGROUND_OPACITY, null, Float.class));
206 if (pAlpha != null) {
207 alpha = pAlpha;
208 }
209 dashesBackground = new Color(dashesBackground.getRed(), dashesBackground.getGreen(),
210 dashesBackground.getBlue(), alpha);
211 }
212
213 Integer cap = null;
214 Keyword capKW = c.get(type.prefix + "linecap", null, Keyword.class);
215 if (capKW != null) {
216 if ("none".equals(capKW.val)) {
217 cap = BasicStroke.CAP_BUTT;
218 } else if ("round".equals(capKW.val)) {
219 cap = BasicStroke.CAP_ROUND;
220 } else if ("square".equals(capKW.val)) {
221 cap = BasicStroke.CAP_SQUARE;
222 }
223 }
224 if (cap == null) {
225 cap = dashes != null ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
226 }
227
228 Integer join = null;
229 Keyword joinKW = c.get(type.prefix + "linejoin", null, Keyword.class);
230 if (joinKW != null) {
231 if ("round".equals(joinKW.val)) {
232 join = BasicStroke.JOIN_ROUND;
233 } else if ("miter".equals(joinKW.val)) {
234 join = BasicStroke.JOIN_MITER;
235 } else if ("bevel".equals(joinKW.val)) {
236 join = BasicStroke.JOIN_BEVEL;
237 }
238 }
239 if (join == null) {
240 join = BasicStroke.JOIN_ROUND;
241 }
242
243 float miterlimit = c.get(type.prefix + "miterlimit", 10f, Float.class);
244 if (miterlimit < 1f) {
245 miterlimit = 10f;
246 }
247
248 BasicStroke line = new BasicStroke(width, cap, join, miterlimit, dashes, dashesOffset);
249 BasicStroke dashesLine = null;
250
251 if (dashes != null && dashesBackground != null) {
252 float[] dashes2 = new float[dashes.length];
253 System.arraycopy(dashes, 0, dashes2, 1, dashes.length - 1);
254 dashes2[0] = dashes[dashes.length-1];
255 dashesLine = new BasicStroke(width, cap, join, miterlimit, dashes2, dashes2[0] + dashesOffset);
256 }
257
258 return new LineElemStyle(c, type.default_major_z_index, line, color, dashesLine, dashesBackground, offset, realWidth);
259 }
260
261 @Override
262 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member) {
263 Way w = (Way)primitive;
264 /* show direction arrows, if draw.segment.relevant_directions_only is not set,
265 the way is tagged with a direction key
266 (even if the tag is negated as in oneway=false) or the way is selected */
267 boolean showOrientation = !isModifier && (selected || paintSettings.isShowDirectionArrow()) && !paintSettings.isUseRealWidth();
268 boolean showOneway = !isModifier && !selected &&
269 !paintSettings.isUseRealWidth() &&
270 paintSettings.isShowOnewayArrow() && w.hasDirectionKeys();
271 boolean onewayReversed = w.reversedDirection();
272 /* head only takes over control if the option is true,
273 the direction should be shown at all and not only because it's selected */
274 boolean showOnlyHeadArrowOnly = showOrientation && !selected && paintSettings.isShowHeadArrowOnly();
275 Node lastN;
276
277 Color myDashedColor = dashesBackground;
278 BasicStroke myLine = line, myDashLine = dashesLine;
279 if (realWidth > 0 && paintSettings.isUseRealWidth() && !showOrientation) {
280 float myWidth = (int) (100 / (float) (painter.getCircum() / realWidth));
281 if (myWidth < line.getLineWidth()) {
282 myWidth = line.getLineWidth();
283 }
284 myLine = new BasicStroke(myWidth, line.getEndCap(), line.getLineJoin(),
285 line.getMiterLimit(), line.getDashArray(), line.getDashPhase());
286 if (dashesLine != null) {
287 myDashLine = new BasicStroke(myWidth, dashesLine.getEndCap(), dashesLine.getLineJoin(),
288 dashesLine.getMiterLimit(), dashesLine.getDashArray(), dashesLine.getDashPhase());
289 }
290 }
291
292 Color myColor = color;
293 if (selected) {
294 myColor = paintSettings.getSelectedColor(color.getAlpha());
295 } else if (member) {
296 myColor = paintSettings.getRelationSelectedColor(color.getAlpha());
297 } else if(w.isDisabled()) {
298 myColor = paintSettings.getInactiveColor();
299 myDashedColor = paintSettings.getInactiveColor();
300 }
301
302 painter.drawWay(w, myColor, myLine, myDashLine, myDashedColor, offset, showOrientation,
303 showOnlyHeadArrowOnly, showOneway, onewayReversed);
304
305 if(paintSettings.isShowOrderNumber() && !painter.isInactiveMode()) {
306 int orderNumber = 0;
307 lastN = null;
308 for(Node n : w.getNodes()) {
309 if(lastN != null) {
310 orderNumber++;
311 painter.drawOrderNumber(lastN, n, orderNumber, myColor);
312 }
313 lastN = n;
314 }
315 }
316 }
317
318 @Override
319 public boolean isProperLineStyle() {
320 return !isModifier;
321 }
322
323 @Override
324 public boolean equals(Object obj) {
325 if (obj == null || getClass() != obj.getClass())
326 return false;
327 if (!super.equals(obj))
328 return false;
329 final LineElemStyle other = (LineElemStyle) obj;
330 return Objects.equals(line, other.line) &&
331 Objects.equals(color, other.color) &&
332 Objects.equals(dashesLine, other.dashesLine) &&
333 Objects.equals(dashesBackground, other.dashesBackground) &&
334 offset == other.offset &&
335 realWidth == other.realWidth;
336 }
337
338 @Override
339 public int hashCode() {
340 int hash = super.hashCode();
341 hash = 29 * hash + line.hashCode();
342 hash = 29 * hash + color.hashCode();
343 hash = 29 * hash + (dashesLine != null ? dashesLine.hashCode() : 0);
344 hash = 29 * hash + (dashesBackground != null ? dashesBackground.hashCode() : 0);
345 hash = 29 * hash + Float.floatToIntBits(offset);
346 hash = 29 * hash + Float.floatToIntBits(realWidth);
347 return hash;
348 }
349
350 @Override
351 public String toString() {
352 return "LineElemStyle{" + super.toString() + "width=" + line.getLineWidth() +
353 " realWidth=" + realWidth + " color=" + Utils.toString(color) +
354 " dashed=" + Arrays.toString(line.getDashArray()) +
355 (line.getDashPhase() == 0f ? "" : " dashesOffses=" + line.getDashPhase()) +
356 " dashedColor=" + Utils.toString(dashesBackground) +
357 " linejoin=" + linejoinToString(line.getLineJoin()) +
358 " linecap=" + linecapToString(line.getEndCap()) +
359 (offset == 0 ? "" : " offset=" + offset) +
360 '}';
361 }
362
363 public String linejoinToString(int linejoin) {
364 switch (linejoin) {
365 case BasicStroke.JOIN_BEVEL: return "bevel";
366 case BasicStroke.JOIN_ROUND: return "round";
367 case BasicStroke.JOIN_MITER: return "miter";
368 default: return null;
369 }
370 }
371 public String linecapToString(int linecap) {
372 switch (linecap) {
373 case BasicStroke.CAP_BUTT: return "none";
374 case BasicStroke.CAP_ROUND: return "round";
375 case BasicStroke.CAP_SQUARE: return "square";
376 default: return null;
377 }
378 }
379}
Note: See TracBrowser for help on using the repository browser.