Ticket #12282: xml_removal.patch
File xml_removal.patch, 49.4 KB (added by , 8 years ago) |
---|
-
data/mappaint-style.xsd
1 <?xml version="1.0" encoding="UTF-8"?>2 <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://josm.openstreetmap.de/mappaint-style-1.0"3 xmlns:tns="http://josm.openstreetmap.de/mappaint-style-1.0" elementFormDefault="qualified">4 5 <!--6 Localized attributes (for example de.description are not supported by7 xsd, so root element needs <anyAttribute/>8 -->9 10 <element name="rules" type="tns:root"/>11 12 <complexType name="root">13 <sequence>14 <choice minOccurs="0" maxOccurs="unbounded">15 <element name="rule" type="tns:rule" />16 </choice>17 </sequence>18 <attribute name="name" type="string" />19 <attribute name="author" type="string" />20 <attribute name="version" type="string" />21 <attribute name="shortdescription" type="string" />22 <attribute name="description" type="string" />23 <attribute name="link" type="string"/>24 <attribute name="icon" type="string"/>25 26 <anyAttribute processContents="skip"/>27 </complexType>28 29 <!-- TODO: ensure that at least one of results exists, but only one of each element, except for linemod which may have more,30 scale is totally optional, but each of the two may come only once -->31 <complexType name="rule">32 <sequence>33 <element name="condition" type="tns:condition" minOccurs="1" maxOccurs="unbounded" />34 <choice minOccurs="1" maxOccurs="unbounded" >35 <group ref="tns:results" />36 <group ref="tns:scale" />37 </choice>38 </sequence>39 </complexType>40 41 <group name="results">42 <choice>43 <element name="icon" type="tns:icon" />44 <element name="area" type="tns:area" />45 <element name="line" type="tns:line" />46 <element name="linemod" type="tns:linemod" maxOccurs="unbounded" />47 </choice>48 </group>49 50 <group name="scale">51 <choice>52 <element name="scale_min" type="integer" />53 <element name="scale_max" type="integer" />54 </choice>55 </group>56 57 <complexType name="condition">58 <!-- TODO restrict to k, k+v or k+b, other attribute combinations are illegal -->59 <attribute name="k" type="string" use="required" />60 <attribute name="v" type="string" />61 <attribute name="b" type="tns:yesno" />62 </complexType>63 64 <complexType name="icon">65 <attribute name="src" type="string" use="required" />66 <attribute name="annotate" type="boolean" />67 <attribute name="priority" type="integer" />68 </complexType>69 70 <complexType name="line">71 <attribute name="width" type="integer" />72 <attribute name="dashed" type="tns:dashed" />73 <attribute name="realwidth" type="integer" />74 <attribute name="colour" type="tns:color" />75 <attribute name="dashedcolour" type="tns:color" />76 <attribute name="priority" type="integer" />77 </complexType>78 79 <complexType name="area">80 <attribute name="colour" type="tns:color" />81 <attribute name="closed" type="boolean" />82 <attribute name="priority" type="integer" />83 </complexType>84 85 <complexType name="linemod">86 <attribute name="dashed" type="tns:dashed" />87 <attribute name="realwidth" type="integer" />88 <attribute name="colour" type="tns:color" />89 <attribute name="dashedcolour" type="tns:color" />90 <attribute name="mode" type="tns:modifier_mode" use="required" />91 <attribute name="width" type="tns:width" />92 </complexType>93 94 <simpleType name="yesno">95 <restriction base="string">96 <enumeration value="yes"/>97 <enumeration value="no"/>98 </restriction>99 </simpleType>100 101 <simpleType name="dashed">102 <restriction base="string">103 <pattern value="\d+(,\d+)*"/>104 <pattern value="(true|false)"/>105 </restriction>106 </simpleType>107 108 <simpleType name="modifier_mode">109 <restriction base="string">110 <enumeration value="under"/>111 <enumeration value="over"/>112 </restriction>113 </simpleType>114 115 <simpleType name="color">116 <restriction base="string">117 <pattern value="([a-z0-9_]+#)?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?"/>118 <!-- name#color or color only, where color is 6 or 8 hex digits -->119 </restriction>120 </simpleType>121 122 <simpleType name="width">123 <restriction base="string">124 <pattern value="\d+"/>125 <pattern value="[+-]\d+"/>126 <pattern value="\d+%"/>127 </restriction>128 </simpleType>129 </schema> -
src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDialog.java
38 38 import org.openstreetmap.josm.gui.NavigatableComponent; 39 39 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 40 40 import org.openstreetmap.josm.gui.mappaint.Cascade; 41 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;42 41 import org.openstreetmap.josm.gui.mappaint.ElemStyles; 43 42 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles; 44 43 import org.openstreetmap.josm.gui.mappaint.MultiCascade; … … 46 45 import org.openstreetmap.josm.gui.mappaint.StyleElementList; 47 46 import org.openstreetmap.josm.gui.mappaint.StyleSource; 48 47 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource; 49 import org.openstreetmap.josm.gui.mappaint. xml.XmlStyleSource;48 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement; 50 49 import org.openstreetmap.josm.gui.util.GuiHelper; 51 50 import org.openstreetmap.josm.gui.widgets.JosmTextArea; 52 51 import org.openstreetmap.josm.tools.GBC; … … 422 421 } 423 422 424 423 private static String getSort(StyleSource s) { 425 if (s instanceof XmlStyleSource) { 426 return tr("xml"); 427 } else if (s instanceof MapCSSStyleSource) { 424 if (s instanceof MapCSSStyleSource) { 428 425 return tr("mapcss"); 429 426 } else { 430 427 return tr("unknown"); -
src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
5 5 6 6 import java.io.File; 7 7 import java.io.IOException; 8 import java.io.InputStreamReader;9 import java.nio.charset.StandardCharsets;10 8 import java.util.ArrayList; 11 9 import java.util.Arrays; 12 10 import java.util.Collection; … … 29 27 import org.openstreetmap.josm.gui.mappaint.styleelement.MapImage; 30 28 import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement; 31 29 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement; 32 import org.openstreetmap.josm.gui.mappaint.xml.XmlStyleSource;33 30 import org.openstreetmap.josm.gui.preferences.SourceEntry; 34 31 import org.openstreetmap.josm.gui.preferences.map.MapPaintPreference.MapPaintPrefHelper; 35 32 import org.openstreetmap.josm.gui.progress.ProgressMonitor; … … 279 276 } 280 277 281 278 private static StyleSource fromSourceEntry(SourceEntry entry) { 282 CachedFile cf = null;283 279 try { 284 Set<String> mimes = new HashSet<>(); 285 mimes.addAll(Arrays.asList(XmlStyleSource.XML_STYLE_MIME_TYPES.split(", "))); 286 mimes.addAll(Arrays.asList(MapCSSStyleSource.MAPCSS_STYLE_MIME_TYPES.split(", "))); 287 cf = new CachedFile(entry.url).setHttpAccept(Utils.join(", ", mimes)); 288 String zipEntryPath = cf.findZipEntryPath("mapcss", "style"); 289 if (zipEntryPath != null) { 290 entry.isZip = true; 291 entry.zipEntryPath = zipEntryPath; 292 return new MapCSSStyleSource(entry); 293 } 294 zipEntryPath = cf.findZipEntryPath("xml", "style"); 295 if (zipEntryPath != null) 296 return new XmlStyleSource(entry); 297 if (Utils.hasExtension(entry.url, "mapcss")) 298 return new MapCSSStyleSource(entry); 299 if (Utils.hasExtension(entry.url, "xml")) 300 return new XmlStyleSource(entry); 301 else { 302 try (InputStreamReader reader = new InputStreamReader(cf.getInputStream(), StandardCharsets.UTF_8)) { 303 WHILE: while (true) { 304 int c = reader.read(); 305 switch (c) { 306 case -1: 307 break WHILE; 308 case ' ': 309 case '\t': 310 case '\n': 311 case '\r': 312 continue; 313 case '<': 314 return new XmlStyleSource(entry); 315 default: 316 return new MapCSSStyleSource(entry); 317 } 318 } 280 Set<String> mimes = new HashSet<>(Arrays.asList(MapCSSStyleSource.MAPCSS_STYLE_MIME_TYPES.split(", "))); 281 try (CachedFile cf = new CachedFile(entry.url).setHttpAccept(Utils.join(", ", mimes))) { 282 String zipEntryPath = cf.findZipEntryPath("mapcss", "style"); 283 if (zipEntryPath != null) { 284 entry.isZip = true; 285 entry.zipEntryPath = zipEntryPath; 286 return new MapCSSStyleSource(entry); 319 287 } 320 Main.warn("Could not detect style type. Using default (xml).");321 return new XmlStyleSource(entry);322 288 } 323 } catch (IOException e) { 289 return new MapCSSStyleSource(entry); 290 } catch (Exception e) { 324 291 Main.warn(tr("Failed to load Mappaint styles from ''{0}''. Exception was: {1}", entry.url, e.toString())); 325 292 Main.error(e); 326 } finally {327 if (cf != null) {328 cf.close();329 }330 293 } 331 294 return null; 332 295 } -
src/org/openstreetmap/josm/gui/mappaint/xml/AreaPrototype.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import java.awt.Color;5 6 import org.openstreetmap.josm.gui.mappaint.Range;7 8 public class AreaPrototype extends Prototype {9 public Color color;10 public boolean closed; // if true, it does not apply to unclosed ways11 12 public AreaPrototype(AreaPrototype a, Range range) {13 super(range);14 this.color = a.color;15 this.closed = a.closed;16 this.priority = a.priority;17 this.conditions = a.conditions;18 }19 20 public AreaPrototype() {21 init();22 }23 24 public final void init() {25 priority = 0;26 range = Range.ZERO_TO_INFINITY;27 closed = false;28 color = null;29 }30 } -
src/org/openstreetmap/josm/gui/mappaint/xml/IconPrototype.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;5 import org.openstreetmap.josm.gui.mappaint.Range;6 7 public class IconPrototype extends Prototype {8 9 public IconReference icon;10 public Boolean annotate;11 12 public IconPrototype(IconPrototype i, Range range) {13 super(range);14 this.icon = i.icon;15 this.annotate = i.annotate;16 this.priority = i.priority;17 this.conditions = i.conditions;18 }19 20 /**21 * Constructs a new {@code IconPrototype}.22 */23 public IconPrototype() {24 init();25 }26 27 public final void init() {28 priority = 0;29 range = Range.ZERO_TO_INFINITY;30 icon = null;31 annotate = null;32 }33 } -
src/org/openstreetmap/josm/gui/mappaint/xml/LinePrototype.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import java.awt.Color;5 import java.util.List;6 7 import org.openstreetmap.josm.Main;8 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;9 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;10 import org.openstreetmap.josm.gui.mappaint.Range;11 import org.openstreetmap.josm.tools.I18n;12 13 public class LinePrototype extends Prototype {14 15 protected int width;16 public Integer realWidth; // the real width of this line in meter17 public Color color;18 protected List<Float> dashed;19 public Color dashedColor;20 21 public LinePrototype(LinePrototype s, Range range) {22 super(range);23 this.width = s.width;24 this.realWidth = s.realWidth;25 this.color = s.color;26 this.dashed = s.dashed;27 this.dashedColor = s.dashedColor;28 this.priority = s.priority;29 this.conditions = s.conditions;30 }31 32 /**33 * Constructs a new {@code LinePrototype}.34 */35 public LinePrototype() {36 init();37 }38 39 public void init() {40 priority = 0;41 range = Range.ZERO_TO_INFINITY;42 width = -1;43 realWidth = null;44 dashed = null;45 dashedColor = null;46 color = PaintColors.UNTAGGED.get();47 }48 49 public List<Float> getDashed() {50 return dashed;51 }52 53 public void setDashed(List<Float> dashed) {54 if (dashed == null || dashed.isEmpty()) {55 this.dashed = null;56 return;57 }58 59 boolean found = false;60 for (Float f : dashed) {61 if (f == null) {62 this.dashed = null;63 return;64 }65 if (f > 0) {66 found = true;67 }68 if (f < 0) {69 Main.error(I18n.tr("Illegal dash pattern, values must be positive"));70 this.dashed = null;71 return;72 }73 }74 if (found) {75 this.dashed = dashed;76 } else {77 Main.error(I18n.tr("Illegal dash pattern, at least one value must be > 0"));78 }79 }80 81 public int getWidth() {82 if (width == -1)83 return MapPaintSettings.INSTANCE.getDefaultSegmentWidth();84 return width;85 }86 87 public void setWidth(int width) {88 this.width = width;89 }90 } -
src/org/openstreetmap/josm/gui/mappaint/xml/LinemodPrototype.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import org.openstreetmap.josm.gui.mappaint.Range;5 6 public class LinemodPrototype extends LinePrototype implements Comparable<LinemodPrototype> {7 8 public enum WidthMode { ABSOLUTE, PERCENT, OFFSET }9 10 public WidthMode widthMode;11 public boolean over;12 13 public LinemodPrototype(LinemodPrototype s, Range range) {14 super(s, range);15 this.over = s.over;16 this.widthMode = s.widthMode;17 }18 19 /**20 * Constructs a new {@code LinemodPrototype}.21 */22 public LinemodPrototype() {23 init();24 }25 26 @Override27 public final void init() {28 super.init();29 over = true;30 widthMode = WidthMode.ABSOLUTE;31 }32 33 /**34 * get width for overlays35 * @param ref reference width36 * @return width according to {@link #widthMode} with a minimal value of 137 */38 public float getWidth(float ref) {39 float res;40 if (widthMode == WidthMode.ABSOLUTE) {41 res = width;42 } else if (widthMode == WidthMode.OFFSET) {43 res = ref + width;44 } else {45 if (width < 0) {46 res = 0;47 } else {48 res = ref*width/100;49 }50 }51 return res <= 0 ? 1 : res;52 }53 54 @Override55 public int getWidth() {56 throw new UnsupportedOperationException();57 }58 59 @Override60 public int compareTo(LinemodPrototype s) {61 if (s.priority != priority)62 return s.priority > priority ? 1 : -1;63 if (!over && s.over)64 return -1;65 // we have no idea how to order other objects :-)66 return 0;67 }68 } -
src/org/openstreetmap/josm/gui/mappaint/xml/Prototype.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import java.util.Collection;5 6 import org.openstreetmap.josm.data.osm.OsmPrimitive;7 import org.openstreetmap.josm.data.osm.OsmUtils;8 import org.openstreetmap.josm.gui.mappaint.Range;9 10 public abstract class Prototype {11 // zoom range to display the feature12 public Range range;13 14 public int priority;15 public String code;16 public Collection<XmlCondition> conditions;17 18 public Prototype(Range range) {19 this.range = range;20 }21 22 /**23 * Constructs a new {@code Prototype}.24 */25 public Prototype() {26 // Allows subclassing27 }28 29 public String getCode() {30 if (code == null) {31 if (conditions == null || conditions.isEmpty()) {32 code = "";33 } else {34 final StringBuilder sb = new StringBuilder();35 for (XmlCondition r: conditions) {36 r.appendCode(sb);37 }38 code = sb.toString();39 }40 }41 return code;42 }43 44 public boolean check(OsmPrimitive primitive) {45 if (conditions == null)46 return true;47 for (XmlCondition r : conditions) {48 String k = primitive.get(r.key);49 50 if (k == null || (r.value != null && !k.equals(r.value)))51 return false;52 53 String bv = OsmUtils.getNamedOsmBoolean(r.boolValue);54 55 if (bv != null && !bv.equals(OsmUtils.getNamedOsmBoolean(k)))56 return false;57 }58 return true;59 }60 } -
src/org/openstreetmap/josm/gui/mappaint/xml/XmlCondition.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import org.openstreetmap.josm.data.osm.OsmUtils;5 6 public class XmlCondition {7 8 public String key;9 public String value;10 public String boolValue;11 12 public XmlCondition() {13 init();14 }15 16 public XmlCondition(XmlCondition c) {17 key = c.key;18 value = c.value;19 boolValue = c.boolValue;20 }21 22 public String getKey() {23 if (value != null)24 return 'n' + key + '=' + value;25 else if (boolValue != null)26 return 'b' + key + '=' + OsmUtils.getNamedOsmBoolean(boolValue);27 else28 return 'x' + key;29 }30 31 public final void init() {32 key = value = boolValue = null;33 }34 35 @Override36 public String toString() {37 return "Rule["+key+','+(boolValue != null ? "b="+boolValue : "v="+value)+']';38 }39 40 public void appendCode(StringBuilder sb) {41 sb.append("[k=").append(key);42 43 if (boolValue != null)44 sb.append(",b=").append(boolValue);45 else46 sb.append(",v=").append(value);47 48 sb.append(']');49 }50 } -
src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import static org.openstreetmap.josm.tools.I18n.tr;5 6 import java.io.IOException;7 import java.io.InputStream;8 import java.io.InputStreamReader;9 import java.nio.charset.StandardCharsets;10 import java.util.Collection;11 import java.util.Collections;12 import java.util.HashMap;13 import java.util.LinkedList;14 import java.util.List;15 import java.util.Map;16 17 import org.openstreetmap.josm.Main;18 import org.openstreetmap.josm.data.osm.Node;19 import org.openstreetmap.josm.data.osm.OsmPrimitive;20 import org.openstreetmap.josm.data.osm.OsmUtils;21 import org.openstreetmap.josm.data.osm.Relation;22 import org.openstreetmap.josm.data.osm.Way;23 import org.openstreetmap.josm.gui.mappaint.Cascade;24 import org.openstreetmap.josm.gui.mappaint.Keyword;25 import org.openstreetmap.josm.gui.mappaint.MultiCascade;26 import org.openstreetmap.josm.gui.mappaint.Range;27 import org.openstreetmap.josm.gui.mappaint.StyleKeys;28 import org.openstreetmap.josm.gui.mappaint.StyleSource;29 import org.openstreetmap.josm.gui.preferences.SourceEntry;30 import org.openstreetmap.josm.io.CachedFile;31 import org.openstreetmap.josm.tools.Utils;32 import org.openstreetmap.josm.tools.XmlObjectParser;33 import org.xml.sax.SAXException;34 import org.xml.sax.SAXParseException;35 36 public class XmlStyleSource extends StyleSource implements StyleKeys {37 38 /**39 * The accepted MIME types sent in the HTTP Accept header.40 * @since 686741 */42 public static final String XML_STYLE_MIME_TYPES =43 "application/xml, text/xml, text/plain; q=0.8, application/zip, application/octet-stream; q=0.5";44 45 protected final Map<String, IconPrototype> icons = new HashMap<>();46 protected final Map<String, LinePrototype> lines = new HashMap<>();47 protected final Map<String, LinemodPrototype> modifiers = new HashMap<>();48 protected final Map<String, AreaPrototype> areas = new HashMap<>();49 protected final List<IconPrototype> iconsList = new LinkedList<>();50 protected final List<LinePrototype> linesList = new LinkedList<>();51 protected final List<LinemodPrototype> modifiersList = new LinkedList<>();52 protected final List<AreaPrototype> areasList = new LinkedList<>();53 54 public XmlStyleSource(String url, String name, String shortdescription) {55 super(url, name, shortdescription);56 }57 58 public XmlStyleSource(SourceEntry entry) {59 super(entry);60 }61 62 @Override63 protected void init() {64 super.init();65 icons.clear();66 lines.clear();67 modifiers.clear();68 areas.clear();69 iconsList.clear();70 linesList.clear();71 modifiersList.clear();72 areasList.clear();73 }74 75 @Override76 public void loadStyleSource() {77 init();78 try {79 try (80 InputStream in = getSourceInputStream();81 InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8)82 ) {83 XmlObjectParser parser = new XmlObjectParser(new XmlStyleSourceHandler(this));84 parser.startWithValidation(reader,85 Main.getXMLBase()+"/mappaint-style-1.0",86 "resource://data/mappaint-style.xsd");87 while (parser.hasNext());88 }89 } catch (IOException e) {90 Main.warn(tr("Failed to load Mappaint styles from ''{0}''. Exception was: {1}", url, e.toString()));91 Main.error(e);92 logError(e);93 } catch (SAXParseException e) {94 Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: [{1}:{2}] {3}",95 url, e.getLineNumber(), e.getColumnNumber(), e.getMessage()));96 Main.error(e);97 logError(e);98 } catch (SAXException e) {99 Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));100 Main.error(e);101 logError(e);102 }103 }104 105 @Override106 public InputStream getSourceInputStream() throws IOException {107 CachedFile cf = getCachedFile();108 InputStream zip = cf.findZipEntryInputStream("xml", "style");109 if (zip != null) {110 zipIcons = cf.getFile();111 return zip;112 } else {113 zipIcons = null;114 return cf.getInputStream();115 }116 }117 118 @Override119 @SuppressWarnings("resource")120 public CachedFile getCachedFile() throws IOException {121 return new CachedFile(url).setHttpAccept(XML_STYLE_MIME_TYPES); // NOSONAR122 }123 124 private static class WayPrototypesRecord {125 public LinePrototype line;126 public List<LinemodPrototype> linemods;127 public AreaPrototype area;128 }129 130 private <T extends Prototype> T update(T current, T candidate, Double scale, MultiCascade mc) {131 if (requiresUpdate(current, candidate, scale, mc))132 return candidate;133 else134 return current;135 }136 137 /**138 * checks whether a certain match is better than the current match139 * @param current can be null140 * @param candidate the new Prototype that could be used instead141 * @param scale ignored if null, otherwise checks if scale is within the range of candidate142 * @param mc side effect: update the valid region for the current MultiCascade143 * @return {@code true} if {@code candidate} is better than the current match144 */145 private static boolean requiresUpdate(Prototype current, Prototype candidate, Double scale, MultiCascade mc) {146 if (current == null || candidate.priority >= current.priority) {147 if (scale == null)148 return true;149 150 if (candidate.range.contains(scale)) {151 mc.range = Range.cut(mc.range, candidate.range);152 return true;153 } else {154 mc.range = mc.range.reduceAround(scale, candidate.range);155 return false;156 }157 }158 return false;159 }160 161 private IconPrototype getNode(OsmPrimitive primitive, Double scale, MultiCascade mc) {162 IconPrototype icon = null;163 for (String key : primitive.keySet()) {164 String val = primitive.get(key);165 IconPrototype p;166 if ((p = icons.get('n' + key + '=' + val)) != null) {167 icon = update(icon, p, scale, mc);168 }169 if ((p = icons.get('b' + key + '=' + OsmUtils.getNamedOsmBoolean(val))) != null) {170 icon = update(icon, p, scale, mc);171 }172 if ((p = icons.get('x' + key)) != null) {173 icon = update(icon, p, scale, mc);174 }175 }176 for (IconPrototype s : iconsList) {177 if (s.check(primitive)) {178 icon = update(icon, s, scale, mc);179 }180 }181 return icon;182 }183 184 /**185 * @param primitive OSM primitive186 * @param closed The primitive is a closed way or we pretend it is closed.187 * This is useful for multipolygon relations and outer ways of untagged188 * multipolygon relations.189 * @param p helper190 * @param scale scale191 * @param mc multi cascade192 */193 private void get(OsmPrimitive primitive, boolean closed, WayPrototypesRecord p, Double scale, MultiCascade mc) {194 String lineIdx = null;195 Map<String, LinemodPrototype> overlayMap = new HashMap<>();196 boolean isNotArea = primitive.isKeyFalse("area");197 for (String key : primitive.keySet()) {198 String val = primitive.get(key);199 AreaPrototype styleArea;200 LinePrototype styleLine;201 LinemodPrototype styleLinemod;202 String idx = 'n' + key + '=' + val;203 if ((styleArea = areas.get(idx)) != null && (closed || !styleArea.closed) && !isNotArea) {204 p.area = update(p.area, styleArea, scale, mc);205 }206 if ((styleLine = lines.get(idx)) != null) {207 if (requiresUpdate(p.line, styleLine, scale, mc)) {208 p.line = styleLine;209 lineIdx = idx;210 }211 }212 if ((styleLinemod = modifiers.get(idx)) != null) {213 if (requiresUpdate(null, styleLinemod, scale, mc)) {214 overlayMap.put(idx, styleLinemod);215 }216 }217 idx = 'b' + key + '=' + OsmUtils.getNamedOsmBoolean(val);218 if ((styleArea = areas.get(idx)) != null && (closed || !styleArea.closed) && !isNotArea) {219 p.area = update(p.area, styleArea, scale, mc);220 }221 if ((styleLine = lines.get(idx)) != null) {222 if (requiresUpdate(p.line, styleLine, scale, mc)) {223 p.line = styleLine;224 lineIdx = idx;225 }226 }227 if ((styleLinemod = modifiers.get(idx)) != null) {228 if (requiresUpdate(null, styleLinemod, scale, mc)) {229 overlayMap.put(idx, styleLinemod);230 }231 }232 idx = 'x' + key;233 if ((styleArea = areas.get(idx)) != null && (closed || !styleArea.closed) && !isNotArea) {234 p.area = update(p.area, styleArea, scale, mc);235 }236 if ((styleLine = lines.get(idx)) != null) {237 if (requiresUpdate(p.line, styleLine, scale, mc)) {238 p.line = styleLine;239 lineIdx = idx;240 }241 }242 if ((styleLinemod = modifiers.get(idx)) != null) {243 if (requiresUpdate(null, styleLinemod, scale, mc)) {244 overlayMap.put(idx, styleLinemod);245 }246 }247 }248 for (AreaPrototype s : areasList) {249 if ((closed || !s.closed) && !isNotArea && s.check(primitive)) {250 p.area = update(p.area, s, scale, mc);251 }252 }253 for (LinePrototype s : linesList) {254 if (s.check(primitive)) {255 p.line = update(p.line, s, scale, mc);256 }257 }258 for (LinemodPrototype s : modifiersList) {259 if (s.check(primitive)) {260 if (requiresUpdate(null, s, scale, mc)) {261 overlayMap.put(s.getCode(), s);262 }263 }264 }265 overlayMap.remove(lineIdx); // do not use overlay if linestyle is from the same rule (example: railway=tram)266 if (!overlayMap.isEmpty()) {267 List<LinemodPrototype> tmp = new LinkedList<>();268 if (p.linemods != null) {269 tmp.addAll(p.linemods);270 }271 tmp.addAll(overlayMap.values());272 Collections.sort(tmp);273 p.linemods = tmp;274 }275 }276 277 public void add(XmlCondition c, Collection<XmlCondition> conditions, Prototype prot) {278 if (conditions != null) {279 prot.conditions = conditions;280 if (prot instanceof IconPrototype) {281 iconsList.add((IconPrototype) prot);282 } else if (prot instanceof LinemodPrototype) {283 modifiersList.add((LinemodPrototype) prot);284 } else if (prot instanceof LinePrototype) {285 linesList.add((LinePrototype) prot);286 } else if (prot instanceof AreaPrototype) {287 areasList.add((AreaPrototype) prot);288 } else289 throw new RuntimeException();290 } else {291 String key = c.getKey();292 prot.code = key;293 if (prot instanceof IconPrototype) {294 icons.put(key, (IconPrototype) prot);295 } else if (prot instanceof LinemodPrototype) {296 modifiers.put(key, (LinemodPrototype) prot);297 } else if (prot instanceof LinePrototype) {298 lines.put(key, (LinePrototype) prot);299 } else if (prot instanceof AreaPrototype) {300 areas.put(key, (AreaPrototype) prot);301 } else302 throw new RuntimeException();303 }304 }305 306 @Override307 public void apply(MultiCascade mc, OsmPrimitive osm, double scale, boolean pretendWayIsClosed) {308 Cascade def = mc.getOrCreateCascade("default");309 boolean useMinMaxScale = Main.pref.getBoolean("mappaint.zoomLevelDisplay", false);310 311 if (osm instanceof Node || (osm instanceof Relation && "restriction".equals(osm.get("type")))) {312 IconPrototype icon = getNode(osm, useMinMaxScale ? scale : null, mc);313 if (icon != null) {314 def.put(ICON_IMAGE, icon.icon);315 if (osm instanceof Node) {316 if (icon.annotate != null) {317 if (icon.annotate) {318 def.put(TEXT, Keyword.AUTO);319 } else {320 def.remove(TEXT);321 }322 }323 }324 }325 } else if (osm instanceof Way || (osm instanceof Relation && ((Relation) osm).isMultipolygon())) {326 WayPrototypesRecord p = new WayPrototypesRecord();327 get(osm, pretendWayIsClosed || !(osm instanceof Way) || ((Way) osm).isClosed(), p, useMinMaxScale ? scale : null, mc);328 if (p.line != null) {329 def.put(WIDTH, new Float(p.line.getWidth()));330 def.putOrClear(REAL_WIDTH, p.line.realWidth != null ? new Float(p.line.realWidth) : null);331 def.putOrClear(COLOR, p.line.color);332 if (p.line.color != null) {333 int alpha = p.line.color.getAlpha();334 if (alpha != 255) {335 def.put(OPACITY, Utils.color_int2float(alpha));336 }337 }338 def.putOrClear(DASHES, p.line.getDashed());339 def.putOrClear(DASHES_BACKGROUND_COLOR, p.line.dashedColor);340 }341 Float refWidth = def.get(WIDTH, null, Float.class);342 if (refWidth != null && p.linemods != null) {343 int numOver = 0, numUnder = 0;344 345 while (mc.hasLayer(String.format("over_%d", ++numOver)));346 while (mc.hasLayer(String.format("under_%d", ++numUnder)));347 348 for (LinemodPrototype mod : p.linemods) {349 Cascade c;350 if (mod.over) {351 String layer = String.format("over_%d", numOver);352 c = mc.getOrCreateCascade(layer);353 c.put(OBJECT_Z_INDEX, new Float(numOver));354 ++numOver;355 } else {356 String layer = String.format("under_%d", numUnder);357 c = mc.getOrCreateCascade(layer);358 c.put(OBJECT_Z_INDEX, new Float(-numUnder));359 ++numUnder;360 }361 c.put(WIDTH, new Float(mod.getWidth(refWidth)));362 c.putOrClear(COLOR, mod.color);363 if (mod.color != null) {364 int alpha = mod.color.getAlpha();365 if (alpha != 255) {366 c.put(OPACITY, Utils.color_int2float(alpha));367 }368 }369 c.putOrClear(DASHES, mod.getDashed());370 c.putOrClear(DASHES_BACKGROUND_COLOR, mod.dashedColor);371 }372 }373 if (p.area != null) {374 def.putOrClear(FILL_COLOR, p.area.color);375 def.putOrClear(TEXT_POSITION, Keyword.CENTER);376 def.putOrClear(TEXT, Keyword.AUTO);377 def.remove(FILL_IMAGE);378 }379 }380 }381 } -
src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSourceHandler.java
1 // License: GPL. For details, see LICENSE file.2 package org.openstreetmap.josm.gui.mappaint.xml;3 4 import java.awt.Color;5 import java.util.Arrays;6 import java.util.Collection;7 import java.util.LinkedList;8 9 import org.openstreetmap.josm.Main;10 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;11 import org.openstreetmap.josm.gui.mappaint.Range;12 import org.openstreetmap.josm.tools.ColorHelper;13 import org.xml.sax.Attributes;14 import org.xml.sax.helpers.DefaultHandler;15 16 public class XmlStyleSourceHandler extends DefaultHandler {17 private boolean inDoc, inRule, inCondition, inLine, inLineMod, inIcon, inArea, inScaleMax, inScaleMin;18 private boolean hadLine, hadLineMod, hadIcon, hadArea;19 private final RuleElem rule = new RuleElem();20 21 private final XmlStyleSource style;22 23 static class RuleElem {24 private final XmlCondition cond = new XmlCondition();25 private Collection<XmlCondition> conditions;26 private double scaleMax;27 private double scaleMin;28 private final LinePrototype line = new LinePrototype();29 private final LinemodPrototype linemod = new LinemodPrototype();30 private final AreaPrototype area = new AreaPrototype();31 private IconPrototype icon = new IconPrototype();32 public void init() {33 conditions = null;34 scaleMax = Double.POSITIVE_INFINITY;35 scaleMin = 0;36 line.init();37 cond.init();38 linemod.init();39 area.init();40 icon.init();41 }42 }43 44 public XmlStyleSourceHandler(XmlStyleSource style) {45 this.style = style;46 inDoc = inRule = inCondition = inLine = inIcon = inArea = false;47 rule.init();48 }49 50 private Color convertColor(String colString) {51 int i = colString.indexOf('#');52 Color ret;53 if (i < 0) {54 ret = Main.pref.getColor("mappaint."+style.getPrefName()+'.'+colString, Color.red);55 } else if (i == 0) {56 ret = ColorHelper.html2color(colString);57 } else {58 ret = Main.pref.getColor("mappaint."+style.getPrefName()+'.'+colString.substring(0, i),59 ColorHelper.html2color(colString.substring(i)));60 }61 return ret;62 }63 64 @Override65 public void startDocument() {66 inDoc = true;67 }68 69 @Override70 public void endDocument() {71 inDoc = false;72 }73 74 private void error(String message) {75 String warning = style.getDisplayString() + " (" + rule.cond.key + '=' + rule.cond.value + "): " + message;76 Main.warn(warning);77 style.logError(new Exception(warning));78 }79 80 private void startElementLine(String qName, Attributes atts, LinePrototype line) {81 for (int count = 0; count < atts.getLength(); count++) {82 switch (atts.getQName(count)) {83 case "width":84 String val = atts.getValue(count);85 if (!(val.startsWith("+") || val.startsWith("-") || val.endsWith("%"))) {86 line.setWidth(Integer.parseInt(val));87 }88 break;89 case "colour":90 line.color = convertColor(atts.getValue(count));91 break;92 case "realwidth":93 line.realWidth = Integer.valueOf(atts.getValue(count));94 break;95 case "dashed":96 Float[] dashed;97 try {98 String[] parts = atts.getValue(count).split(",");99 dashed = new Float[parts.length];100 for (int i = 0; i < parts.length; i++) {101 dashed[i] = (float) Integer.parseInt(parts[i]);102 }103 } catch (NumberFormatException nfe) {104 boolean isDashed = Boolean.parseBoolean(atts.getValue(count));105 if (isDashed) {106 dashed = new Float[]{9f};107 } else {108 dashed = null;109 }110 }111 line.setDashed(dashed == null ? null : Arrays.asList(dashed));112 break;113 case "dashedcolour":114 line.dashedColor = convertColor(atts.getValue(count));115 break;116 case "priority":117 line.priority = Integer.parseInt(atts.getValue(count));118 break;119 case "mode":120 if (line instanceof LinemodPrototype)121 break;122 default:123 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");124 }125 }126 }127 128 private void startElementLinemod(String qName, Attributes atts, LinemodPrototype line) {129 startElementLine(qName, atts, line);130 for (int count = 0; count < atts.getLength(); count++) {131 switch (atts.getQName(count)) {132 case "width":133 String val = atts.getValue(count);134 if (val.startsWith("+")) {135 line.setWidth(Integer.parseInt(val.substring(1)));136 line.widthMode = LinemodPrototype.WidthMode.OFFSET;137 } else if (val.startsWith("-")) {138 line.setWidth(Integer.parseInt(val));139 line.widthMode = LinemodPrototype.WidthMode.OFFSET;140 } else if (val.endsWith("%")) {141 line.setWidth(Integer.parseInt(val.substring(0, val.length()-1)));142 line.widthMode = LinemodPrototype.WidthMode.PERCENT;143 } else {144 line.setWidth(Integer.parseInt(val));145 }146 break;147 case "mode":148 line.over = !"under".equals(atts.getValue(count));149 break;150 }151 }152 }153 154 @Override155 public void startElement(String uri, String name, String qName, Attributes atts) {156 if (inDoc) {157 switch(qName) {158 case "rule":159 inRule = true;160 break;161 case "rules":162 if (style.name == null) {163 style.name = atts.getValue("name");164 }165 if (style.title == null) {166 style.title = atts.getValue("shortdescription");167 }168 if (style.icon == null) {169 style.icon = atts.getValue("icon");170 }171 break;172 case "scale_max":173 inScaleMax = true;174 break;175 case "scale_min":176 inScaleMin = true;177 break;178 case "condition":179 if (inRule) {180 inCondition = true;181 XmlCondition c = rule.cond;182 if (c.key != null) {183 if (rule.conditions == null) {184 rule.conditions = new LinkedList<>();185 }186 rule.conditions.add(new XmlCondition(rule.cond));187 c = new XmlCondition();188 rule.conditions.add(c);189 }190 for (int count = 0; count < atts.getLength(); count++) {191 switch (atts.getQName(count)) {192 case "k":193 c.key = atts.getValue(count);194 break;195 case "v":196 c.value = atts.getValue(count);197 break;198 case "b":199 c.boolValue = atts.getValue(count);200 break;201 default:202 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");203 }204 }205 if (c.key == null) {206 error("The condition has no key!");207 }208 }209 break;210 case "line":211 hadLine = inLine = true;212 startElementLine(qName, atts, rule.line);213 break;214 case "linemod":215 hadLineMod = inLineMod = true;216 startElementLinemod(qName, atts, rule.linemod);217 break;218 case "icon":219 inIcon = true;220 for (int count = 0; count < atts.getLength(); count++) {221 switch (atts.getQName(count)) {222 case "src":223 IconReference icon = new IconReference(atts.getValue(count), style);224 hadIcon = (icon != null);225 rule.icon.icon = icon;226 break;227 case "annotate":228 rule.icon.annotate = Boolean.valueOf(atts.getValue(count));229 break;230 case "priority":231 rule.icon.priority = Integer.parseInt(atts.getValue(count));232 break;233 default:234 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");235 }236 }237 break;238 case "area":239 hadArea = inArea = true;240 for (int count = 0; count < atts.getLength(); count++) {241 switch (atts.getQName(count)) {242 case "colour":243 rule.area.color = convertColor(atts.getValue(count));244 break;245 case "closed":246 rule.area.closed = Boolean.parseBoolean(atts.getValue(count));247 break;248 case "priority":249 rule.area.priority = Integer.parseInt(atts.getValue(count));250 break;251 default:252 error("The element \"" + qName + "\" has unknown attribute \"" + atts.getQName(count) + "\"!");253 }254 }255 break;256 default:257 error("The element \"" + qName + "\" is unknown!");258 }259 }260 }261 262 @Override263 public void endElement(String uri, String name, String qName) {264 if (inRule && "rule".equals(qName)) {265 if (hadLine) {266 style.add(rule.cond, rule.conditions,267 new LinePrototype(rule.line, new Range(rule.scaleMin, rule.scaleMax)));268 }269 if (hadLineMod) {270 style.add(rule.cond, rule.conditions,271 new LinemodPrototype(rule.linemod, new Range(rule.scaleMin, rule.scaleMax)));272 }273 if (hadIcon) {274 style.add(rule.cond, rule.conditions,275 new IconPrototype(rule.icon, new Range(rule.scaleMin, rule.scaleMax)));276 }277 if (hadArea) {278 style.add(rule.cond, rule.conditions,279 new AreaPrototype(rule.area, new Range(rule.scaleMin, rule.scaleMax)));280 }281 inRule = false;282 hadLine = hadLineMod = hadIcon = hadArea = false;283 rule.init();284 } else if (inCondition && "condition".equals(qName)) {285 inCondition = false;286 } else if (inLine && "line".equals(qName)) {287 inLine = false;288 } else if (inLineMod && "linemod".equals(qName)) {289 inLineMod = false;290 } else if (inIcon && "icon".equals(qName)) {291 inIcon = false;292 } else if (inArea && "area".equals(qName)) {293 inArea = false;294 } else if ("scale_max".equals(qName)) {295 inScaleMax = false;296 } else if ("scale_min".equals(qName)) {297 inScaleMin = false;298 }299 }300 301 @Override302 public void characters(char[] ch, int start, int length) {303 if (inScaleMax) {304 rule.scaleMax = Long.parseLong(new String(ch, start, length));305 } else if (inScaleMin) {306 rule.scaleMin = Long.parseLong(new String(ch, start, length));307 }308 }309 } -
src/org/openstreetmap/josm/gui/mappaint/xml/package-info.java
1 // License: GPL. For details, see LICENSE file.2 3 /**4 * Drawing system based on XML map styles. This is a legacy system, not maintained anymore.5 * For reference, see <a href="https://josm.openstreetmap.de/wiki/Styles/LegacyStandard">JOSM wiki</a>6 */7 package org.openstreetmap.josm.gui.mappaint.xml;