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

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

fix #10615 - Inner ways of multipolygon not correctly displayed (regression from r7555)

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