source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java@ 8384

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

squid:S1244 - Floating point numbers should not be tested for equality

  • Property svn:eol-style set to native
File size: 8.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import java.awt.Font;
5import java.util.HashMap;
6import java.util.Map;
7
8import org.openstreetmap.josm.Main;
9import org.openstreetmap.josm.data.osm.OsmPrimitive;
10import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
11import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
12import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
13import org.openstreetmap.josm.tools.Utils;
14
15public abstract class ElemStyle implements StyleKeys {
16
17 protected static final int ICON_IMAGE_IDX = 0;
18 protected static final int ICON_WIDTH_IDX = 1;
19 protected static final int ICON_HEIGHT_IDX = 2;
20 protected static final int ICON_OPACITY_IDX = 3;
21 protected static final int ICON_OFFSET_X_IDX = 4;
22 protected static final int ICON_OFFSET_Y_IDX = 5;
23 public static final String[] ICON_KEYS = {ICON_IMAGE, ICON_WIDTH, ICON_HEIGHT, ICON_OPACITY, ICON_OFFSET_X, ICON_OFFSET_Y};
24 public static final String[] REPEAT_IMAGE_KEYS = {REPEAT_IMAGE, REPEAT_IMAGE_WIDTH, REPEAT_IMAGE_HEIGHT, REPEAT_IMAGE_OPACITY, null, null};
25
26 public float majorZIndex;
27 public float zIndex;
28 public float objectZIndex;
29 public boolean isModifier; // false, if style can serve as main style for the
30 // primitive; true, if it is a highlight or modifier
31
32 public ElemStyle(float major_z_index, float z_index, float object_z_index, boolean isModifier) {
33 this.majorZIndex = major_z_index;
34 this.zIndex = z_index;
35 this.objectZIndex = object_z_index;
36 this.isModifier = isModifier;
37 }
38
39 protected ElemStyle(Cascade c, float default_major_z_index) {
40 majorZIndex = c.get(MAJOR_Z_INDEX, default_major_z_index, Float.class);
41 zIndex = c.get(Z_INDEX, 0f, Float.class);
42 objectZIndex = c.get(OBJECT_Z_INDEX, 0f, Float.class);
43 isModifier = c.get(MODIFIER, Boolean.FALSE, Boolean.class);
44 }
45
46 /**
47 * draws a primitive
48 * @param primitive
49 * @param paintSettings
50 * @param painter
51 * @param selected true, if primitive is selected
52 * @param outermember true, if primitive is not selected and outer member of a selected multipolygon relation
53 * @param member true, if primitive is not selected and member of a selected relation
54 */
55 public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter,
56 boolean selected, boolean outermember, boolean member);
57
58 public boolean isProperLineStyle() {
59 return false;
60 }
61
62 /**
63 * Get a property value of type Width
64 * @param c the cascade
65 * @param key property key for the width value
66 * @param relativeTo reference width. Only needed, when relative width syntax
67 * is used, e.g. "+4".
68 */
69 protected static Float getWidth(Cascade c, String key, Float relativeTo) {
70 Float width = c.get(key, null, Float.class, true);
71 if (width != null) {
72 if (width > 0)
73 return width;
74 } else {
75 Keyword widthKW = c.get(key, null, Keyword.class, true);
76 if (Keyword.THINNEST.equals(widthKW))
77 return 0f;
78 if (Keyword.DEFAULT.equals(widthKW))
79 return (float) MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
80 if (relativeTo != null) {
81 RelativeFloat width_rel = c.get(key, null, RelativeFloat.class, true);
82 if (width_rel != null)
83 return relativeTo + width_rel.val;
84 }
85 }
86 return null;
87 }
88
89 /* ------------------------------------------------------------------------------- */
90 /* cached values */
91 /* ------------------------------------------------------------------------------- */
92 /*
93 * Two preference values and the set of created fonts are cached in order to avoid
94 * expensive lookups and to avoid too many font objects
95 *
96 * FIXME: cached preference values are not updated if the user changes them during
97 * a JOSM session. Should have a listener listening to preference changes.
98 */
99 private static volatile String DEFAULT_FONT_NAME = null;
100 private static volatile Float DEFAULT_FONT_SIZE = null;
101 private static final Object lock = new Object();
102
103 // thread save access (double-checked locking)
104 private static Float getDefaultFontSize() {
105 Float s = DEFAULT_FONT_SIZE;
106 if (s == null) {
107 synchronized (lock) {
108 s = DEFAULT_FONT_SIZE;
109 if (s == null) {
110 DEFAULT_FONT_SIZE = s = (float) Main.pref.getInteger("mappaint.fontsize", 8);
111 }
112 }
113 }
114 return s;
115 }
116
117 private static String getDefaultFontName() {
118 String n = DEFAULT_FONT_NAME;
119 if (n == null) {
120 synchronized (lock) {
121 n = DEFAULT_FONT_NAME;
122 if (n == null) {
123 DEFAULT_FONT_NAME = n = Main.pref.get("mappaint.font", "Droid Sans");
124 }
125 }
126 }
127 return n;
128 }
129
130 private static class FontDescriptor {
131 public String name;
132 public int style;
133 public int size;
134
135 public FontDescriptor(String name, int style, int size){
136 this.name = name;
137 this.style = style;
138 this.size = size;
139 }
140
141 @Override
142 public int hashCode() {
143 final int prime = 31;
144 int result = 1;
145 result = prime * result + ((name == null) ? 0 : name.hashCode());
146 result = prime * result + size;
147 result = prime * result + style;
148 return result;
149 }
150 @Override
151 public boolean equals(Object obj) {
152 if (this == obj)
153 return true;
154 if (obj == null)
155 return false;
156 if (getClass() != obj.getClass())
157 return false;
158 FontDescriptor other = (FontDescriptor) obj;
159 if (name == null) {
160 if (other.name != null)
161 return false;
162 } else if (!name.equals(other.name))
163 return false;
164 if (size != other.size)
165 return false;
166 if (style != other.style)
167 return false;
168 return true;
169 }
170 }
171
172 private static final Map<FontDescriptor, Font> FONT_MAP = new HashMap<>();
173 private static Font getCachedFont(FontDescriptor fd) {
174 Font f = FONT_MAP.get(fd);
175 if (f != null) return f;
176 f = new Font(fd.name, fd.style, fd.size);
177 FONT_MAP.put(fd, f);
178 return f;
179 }
180
181 private static Font getCachedFont(String name, int style, int size){
182 return getCachedFont(new FontDescriptor(name, style, size));
183 }
184
185 protected static Font getFont(Cascade c, String s) {
186 String name = c.get(FONT_FAMILY, getDefaultFontName(), String.class);
187 float size = c.get(FONT_SIZE, getDefaultFontSize(), Float.class);
188 int weight = Font.PLAIN;
189 if ("bold".equalsIgnoreCase(c.get(FONT_WEIGHT, null, String.class))) {
190 weight = Font.BOLD;
191 }
192 int style = Font.PLAIN;
193 if ("italic".equalsIgnoreCase(c.get(FONT_STYLE, null, String.class))) {
194 style = Font.ITALIC;
195 }
196 Font f = getCachedFont(name, style | weight, Math.round(size));
197 if (f.canDisplayUpTo(s) == -1)
198 return f;
199 else {
200 // fallback if the string contains characters that cannot be
201 // rendered by the selected font
202 return getCachedFont("SansSerif", style | weight, Math.round(size));
203 }
204 }
205
206 @Override
207 public boolean equals(Object o) {
208 if (!(o instanceof ElemStyle))
209 return false;
210 ElemStyle s = (ElemStyle) o;
211 return isModifier == s.isModifier &&
212 Utils.equalsEpsilon(majorZIndex, s.majorZIndex) &&
213 Utils.equalsEpsilon(zIndex, s.zIndex) &&
214 Utils.equalsEpsilon(objectZIndex, s.objectZIndex);
215 }
216
217 @Override
218 public int hashCode() {
219 int hash = 5;
220 hash = 41 * hash + Float.floatToIntBits(this.majorZIndex);
221 hash = 41 * hash + Float.floatToIntBits(this.zIndex);
222 hash = 41 * hash + Float.floatToIntBits(this.objectZIndex);
223 hash = 41 * hash + (isModifier ? 1 : 0);
224 return hash;
225 }
226
227 @Override
228 public String toString() {
229 return String.format("z_idx=[%s/%s/%s] ", majorZIndex, zIndex, objectZIndex) + (isModifier ? "modifier " : "");
230 }
231}
Note: See TracBrowser for help on using the repository browser.