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

Last change on this file since 7530 was 7383, checked in by bastiK, 10 years ago

applied #10301 - extend display of maxspeed nodes (patch by Klumbumbus)
Include Droid Sans font in the JOSM binary distribution.
This unifies the font rendering on different platforms and allows geometric constructions with text (as demonstrated for maxspeed). Both regular and bold style are available.

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