source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSourceHandler.java@ 3836

Last change on this file since 3836 was 3836, checked in by bastiK, 13 years ago

mappaint restructuring aimed at mapcss support:

  • area- and line style of multipolygon outer & inner ways are no longer determined by MapPaintVisitor, but the information is calculated in advance and cached
  • cache is aware of zoom level
  • z_index property to allow more fancy styles in future

Performance: when the style cache is filled, painting is the same or ~5% faster. The first painting, which includes style generation, takes ~30% longer than before. (There is potential for optimization, though.) Memory usage unchanged.

  • Property svn:eol-style set to native
File size: 11.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.xml;
3
4import java.awt.Color;
5import java.util.Collection;
6import java.util.LinkedList;
7
8import org.openstreetmap.josm.Main;
9import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
10import org.openstreetmap.josm.gui.mappaint.Range;
11import org.openstreetmap.josm.tools.ColorHelper;
12import org.xml.sax.Attributes;
13import org.xml.sax.helpers.DefaultHandler;
14
15public class XmlStyleSourceHandler extends DefaultHandler
16{
17 private boolean inDoc, inRule, inCondition, inLine, inLineMod, inIcon, inArea, inScaleMax, inScaleMin;
18 private boolean hadLine, hadLineMod, hadIcon, hadArea;
19 private RuleElem rule = new RuleElem();
20
21 XmlStyleSource style;
22
23 static class RuleElem {
24 XmlCondition cond = new XmlCondition();
25 Collection<XmlCondition> conditions;
26 double scaleMax;
27 double scaleMin;
28 LinePrototype line = new LinePrototype();
29 LinemodPrototype linemod = new LinemodPrototype();
30 AreaPrototype area = new AreaPrototype();
31 IconPrototype icon = new IconPrototype();
32 public void init()
33 {
34 conditions = null;
35 scaleMax = Double.POSITIVE_INFINITY;
36 scaleMin = 0;
37 line.init();
38 cond.init();
39 linemod.init();
40 area.init();
41 icon.init();
42 }
43 }
44
45 public XmlStyleSourceHandler(XmlStyleSource style) {
46 this.style = style;
47 inDoc=inRule=inCondition=inLine=inIcon=inArea=false;
48 rule.init();
49 }
50
51 Color convertColor(String colString)
52 {
53 int i = colString.indexOf("#");
54 Color ret;
55 if (i < 0) {
56 ret = Main.pref.getColor("mappaint."+style.getPrefName()+"."+colString, Color.red);
57 } else if(i == 0) {
58 ret = ColorHelper.html2color(colString);
59 } else {
60 ret = Main.pref.getColor("mappaint."+style.getPrefName()+"."+colString.substring(0,i),
61 ColorHelper.html2color(colString.substring(i)));
62 }
63 return ret;
64 }
65
66 @Override public void startDocument() {
67 inDoc = true;
68 }
69
70 @Override public void endDocument() {
71 inDoc = false;
72 }
73
74 private void error(String message) {
75 System.out.println(style.getDisplayString() + " (" + rule.cond.key + "=" + rule.cond.value + "): " + message);
76 }
77
78 private void startElementLine(String qName, Attributes atts, LinePrototype line) {
79 for (int count=0; count<atts.getLength(); count++)
80 {
81 if(atts.getQName(count).equals("width"))
82 {
83 String val = atts.getValue(count);
84 if (! (val.startsWith("+") || val.startsWith("-") || val.endsWith("%"))) {
85 line.setWidth(Integer.parseInt(val));
86 }
87 }
88 else if (atts.getQName(count).equals("colour")) {
89 line.color=convertColor(atts.getValue(count));
90 } else if (atts.getQName(count).equals("realwidth")) {
91 line.realWidth=Integer.parseInt(atts.getValue(count));
92 } else if (atts.getQName(count).equals("dashed")) {
93 float[] dashed;
94 try {
95 String[] parts = atts.getValue(count).split(",");
96 dashed = new float[parts.length];
97 for (int i = 0; i < parts.length; i++) {
98 dashed[i] = (Integer.parseInt(parts[i]));
99 }
100 } catch (NumberFormatException nfe) {
101 boolean isDashed = Boolean.parseBoolean(atts.getValue(count));
102 if(isDashed) {
103 dashed = new float[]{9};
104 } else {
105 dashed = null;
106 }
107 }
108 line.setDashed(dashed);
109 } else if (atts.getQName(count).equals("dashedcolour")) {
110 line.dashedColor=convertColor(atts.getValue(count));
111 } else if(atts.getQName(count).equals("priority")) {
112 line.priority = Integer.parseInt(atts.getValue(count));
113 } else if (!(atts.getQName(count).equals("mode") && line instanceof LinemodPrototype)){
114 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");
115 }
116 }
117 }
118
119 private void startElementLinemod(String qName, Attributes atts, LinemodPrototype line) {
120 startElementLine(qName, atts, line);
121 for (int count=0; count<atts.getLength(); count++)
122 {
123 if(atts.getQName(count).equals("width"))
124 {
125 String val = atts.getValue(count);
126 if(val.startsWith("+"))
127 {
128 line.setWidth(Integer.parseInt(val.substring(1)));
129 line.widthMode = LinemodPrototype.WidthMode.OFFSET;
130 }
131 else if(val.startsWith("-"))
132 {
133 line.setWidth(Integer.parseInt(val));
134 line.widthMode = LinemodPrototype.WidthMode.OFFSET;
135 }
136 else if(val.endsWith("%"))
137 {
138 line.setWidth(Integer.parseInt(val.substring(0, val.length()-1)));
139 line.widthMode = LinemodPrototype.WidthMode.PERCENT;
140 } else {
141 line.setWidth(Integer.parseInt(val));
142 }
143 } else if(atts.getQName(count).equals("mode")) {
144 line.over = !atts.getValue(count).equals("under");
145 }
146 }
147 }
148
149 @Override public void startElement(String uri,String name, String qName, Attributes atts) {
150 if (inDoc==true)
151 {
152 if (qName.equals("rule")) {
153 inRule=true;
154 } else if (qName.equals("rules"))
155 {
156 if (style.name == null) {
157 style.name = atts.getValue("name");
158 }
159 if (style.shortdescription == null) {
160 style.shortdescription = atts.getValue("shortdescription");
161 }
162 }
163 else if (qName.equals("scale_max")) {
164 inScaleMax = true;
165 } else if (qName.equals("scale_min")) {
166 inScaleMin = true;
167 } else if (qName.equals("condition") && inRule)
168 {
169 inCondition=true;
170 XmlCondition c = rule.cond;
171 if(c.key != null)
172 {
173 if(rule.conditions == null) {
174 rule.conditions = new LinkedList<XmlCondition>();
175 }
176 rule.conditions.add(new XmlCondition(rule.cond));
177 c = new XmlCondition();
178 rule.conditions.add(c);
179 }
180 for (int count=0; count<atts.getLength(); count++)
181 {
182 if(atts.getQName(count).equals("k")) {
183 c.key = atts.getValue(count);
184 } else if(atts.getQName(count).equals("v")) {
185 c.value = atts.getValue(count);
186 } else if(atts.getQName(count).equals("b")) {
187 c.boolValue = atts.getValue(count);
188 } else {
189 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");
190 }
191 }
192 if(c.key == null) {
193 error("The condition has no key!");
194 }
195 }
196 else if (qName.equals("line"))
197 {
198 hadLine = inLine = true;
199 startElementLine(qName, atts, rule.line);
200 }
201 else if (qName.equals("linemod"))
202 {
203 hadLineMod = inLineMod = true;
204 startElementLinemod(qName, atts, rule.linemod);
205 }
206 else if (qName.equals("icon"))
207 {
208 inIcon = true;
209 for (int count=0; count<atts.getLength(); count++)
210 {
211 if (atts.getQName(count).equals("src")) {
212 IconReference icon = new IconReference(atts.getValue(count), style);
213 hadIcon = (icon != null);
214 rule.icon.icon = icon;
215 } else if (atts.getQName(count).equals("annotate")) {
216 rule.icon.annotate = Boolean.parseBoolean (atts.getValue(count));
217 } else if(atts.getQName(count).equals("priority")) {
218 rule.icon.priority = Integer.parseInt(atts.getValue(count));
219 } else {
220 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");
221 }
222 }
223 }
224 else if (qName.equals("area"))
225 {
226 hadArea = inArea = true;
227 for (int count=0; count<atts.getLength(); count++)
228 {
229 if (atts.getQName(count).equals("colour")) {
230 rule.area.color=convertColor(atts.getValue(count));
231 } else if (atts.getQName(count).equals("closed")) {
232 rule.area.closed=Boolean.parseBoolean(atts.getValue(count));
233 } else if(atts.getQName(count).equals("priority")) {
234 rule.area.priority = Integer.parseInt(atts.getValue(count));
235 } else {
236 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");
237 }
238 }
239 } else {
240 error("The element \"" + qName + "\" is unknown!");
241 }
242 }
243 }
244
245 @Override public void endElement(String uri,String name, String qName)
246 {
247 if (inRule && qName.equals("rule"))
248 {
249 if(hadLine)
250 {
251 style.add(rule.cond, rule.conditions,
252 new LinePrototype(rule.line, new Range(rule.scaleMin, rule.scaleMax)));
253 }
254 if(hadLineMod)
255 {
256 style.add(rule.cond, rule.conditions,
257 new LinemodPrototype(rule.linemod, new Range(rule.scaleMin, rule.scaleMax)));
258 }
259 if(hadIcon)
260 {
261 style.add(rule.cond, rule.conditions,
262 new IconPrototype(rule.icon, new Range(rule.scaleMin, rule.scaleMax)));
263 }
264 if(hadArea)
265 {
266 style.add(rule.cond, rule.conditions,
267 new AreaPrototype(rule.area, new Range(rule.scaleMin, rule.scaleMax)));
268 }
269 inRule = false;
270 hadLine = hadLineMod = hadIcon = hadArea = false;
271 rule.init();
272 }
273 else if (inCondition && qName.equals("condition")) {
274 inCondition = false;
275 } else if (inLine && qName.equals("line")) {
276 inLine = false;
277 } else if (inLineMod && qName.equals("linemod")) {
278 inLineMod = false;
279 } else if (inIcon && qName.equals("icon")) {
280 inIcon = false;
281 } else if (inArea && qName.equals("area")) {
282 inArea = false;
283 } else if (qName.equals("scale_max")) {
284 inScaleMax = false;
285 } else if (qName.equals("scale_min")) {
286 inScaleMin = false;
287 }
288 }
289
290 @Override public void characters(char ch[], int start, int length)
291 {
292 if (inScaleMax == true) {
293 rule.scaleMax = Long.parseLong(new String(ch, start, length));
294 } else if (inScaleMin == true) {
295 rule.scaleMin = Long.parseLong(new String(ch, start, length));
296 }
297 }
298}
Note: See TracBrowser for help on using the repository browser.