simplify rendertheme 'closed' and 'element' matching
This commit is contained in:
parent
380b5e019d
commit
b410059282
@ -16,7 +16,7 @@ package org.mapsforge.android.rendertheme;
|
||||
|
||||
import org.mapsforge.core.Tag;
|
||||
|
||||
final class AnyMatcher implements ElementMatcher, AttributeMatcher, ClosedMatcher {
|
||||
final class AnyMatcher implements AttributeMatcher {
|
||||
private static final AnyMatcher INSTANCE = new AnyMatcher();
|
||||
|
||||
static AnyMatcher getInstance() {
|
||||
@ -35,26 +35,6 @@ final class AnyMatcher implements ElementMatcher, AttributeMatcher, ClosedMatche
|
||||
return attributeMatcher == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoveredBy(ClosedMatcher closedMatcher) {
|
||||
return closedMatcher == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoveredBy(ElementMatcher elementMatcher) {
|
||||
return elementMatcher == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Closed closed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Element element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Tag[] tags) {
|
||||
return true;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
enum Closed {
|
||||
ANY, NO, YES;
|
||||
class Closed {
|
||||
public static final int ANY = 0;
|
||||
public static final int NO = 1;
|
||||
public static final int YES = 2;
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
interface ClosedMatcher {
|
||||
boolean isCoveredBy(ClosedMatcher closedMatcher);
|
||||
|
||||
boolean matches(Closed closed);
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
final class ClosedWayMatcher implements ClosedMatcher {
|
||||
private static final ClosedWayMatcher INSTANCE = new ClosedWayMatcher();
|
||||
|
||||
static ClosedWayMatcher getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from other classes.
|
||||
*/
|
||||
private ClosedWayMatcher() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoveredBy(ClosedMatcher closedMatcher) {
|
||||
return closedMatcher.matches(Closed.YES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Closed closed) {
|
||||
return closed == Closed.YES;
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,8 @@
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
enum Element {
|
||||
ANY, NODE, WAY;
|
||||
class Element {
|
||||
public static final int ANY = 0;
|
||||
public static final int NODE = 1;
|
||||
public static final int WAY = 2;
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
interface ElementMatcher {
|
||||
boolean isCoveredBy(ElementMatcher elementMatcher);
|
||||
|
||||
boolean matches(Element element);
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
final class ElementNodeMatcher implements ElementMatcher {
|
||||
private static final ElementNodeMatcher INSTANCE = new ElementNodeMatcher();
|
||||
|
||||
static ElementNodeMatcher getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from other classes.
|
||||
*/
|
||||
private ElementNodeMatcher() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoveredBy(ElementMatcher elementMatcher) {
|
||||
return elementMatcher.matches(Element.NODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Element element) {
|
||||
return element == Element.NODE;
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
final class ElementWayMatcher implements ElementMatcher {
|
||||
private static final ElementWayMatcher INSTANCE = new ElementWayMatcher();
|
||||
|
||||
static ElementWayMatcher getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from other classes.
|
||||
*/
|
||||
private ElementWayMatcher() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoveredBy(ElementMatcher elementMatcher) {
|
||||
return elementMatcher.matches(Element.WAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Element element) {
|
||||
return element == Element.WAY;
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.android.rendertheme;
|
||||
|
||||
final class LinearWayMatcher implements ClosedMatcher {
|
||||
private static final LinearWayMatcher INSTANCE = new LinearWayMatcher();
|
||||
|
||||
static LinearWayMatcher getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from other classes.
|
||||
*/
|
||||
private LinearWayMatcher() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoveredBy(ClosedMatcher closedMatcher) {
|
||||
return closedMatcher.matches(Closed.NO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Closed closed) {
|
||||
return closed == Closed.NO;
|
||||
}
|
||||
}
|
||||
@ -19,9 +19,9 @@ import org.mapsforge.core.Tag;
|
||||
class NegativeRule extends Rule {
|
||||
final AttributeMatcher mAttributeMatcher;
|
||||
|
||||
NegativeRule(ElementMatcher elementMatcher, ClosedMatcher closedMatcher, byte zoomMin, byte zoomMax,
|
||||
NegativeRule(int element, int closed, byte zoomMin, byte zoomMax,
|
||||
AttributeMatcher attributeMatcher) {
|
||||
super(elementMatcher, closedMatcher, zoomMin, zoomMax);
|
||||
super(element, closed, zoomMin, zoomMax);
|
||||
|
||||
mAttributeMatcher = attributeMatcher;
|
||||
}
|
||||
@ -29,14 +29,15 @@ class NegativeRule extends Rule {
|
||||
@Override
|
||||
boolean matchesNode(Tag[] tags, byte zoomLevel) {
|
||||
return mZoomMin <= zoomLevel && mZoomMax >= zoomLevel
|
||||
&& (mElementMatcher == null || mElementMatcher.matches(Element.NODE))
|
||||
&& (mElement == Element.NODE || mElement == Element.ANY)
|
||||
&& mAttributeMatcher.matches(tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean matchesWay(Tag[] tags, byte zoomLevel, Closed closed) {
|
||||
boolean matchesWay(Tag[] tags, byte zoomLevel, int closed) {
|
||||
return mZoomMin <= zoomLevel && mZoomMax >= zoomLevel
|
||||
&& (mElementMatcher == null || mElementMatcher.matches(Element.WAY))
|
||||
&& (mClosedMatcher == null || mClosedMatcher.matches(closed)) && mAttributeMatcher.matches(tags);
|
||||
&& (mElement == Element.WAY || mElement == Element.ANY)
|
||||
&& (mClosed == closed || mClosed == Closed.ANY)
|
||||
&& mAttributeMatcher.matches(tags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,9 +20,9 @@ class PositiveRule extends Rule {
|
||||
final AttributeMatcher mKeyMatcher;
|
||||
final AttributeMatcher mValueMatcher;
|
||||
|
||||
PositiveRule(ElementMatcher elementMatcher, ClosedMatcher closedMatcher, byte zoomMin, byte zoomMax,
|
||||
PositiveRule(int element, int closed, byte zoomMin, byte zoomMax,
|
||||
AttributeMatcher keyMatcher, AttributeMatcher valueMatcher) {
|
||||
super(elementMatcher, closedMatcher, zoomMin, zoomMax);
|
||||
super(element, closed, zoomMin, zoomMax);
|
||||
|
||||
if (keyMatcher instanceof AnyMatcher)
|
||||
mKeyMatcher = null;
|
||||
@ -38,16 +38,16 @@ class PositiveRule extends Rule {
|
||||
@Override
|
||||
boolean matchesNode(Tag[] tags, byte zoomLevel) {
|
||||
return mZoomMin <= zoomLevel && mZoomMax >= zoomLevel
|
||||
&& (mElementMatcher == null || mElementMatcher.matches(Element.NODE))
|
||||
&& (mElement == Element.NODE || mElement == Element.ANY)
|
||||
&& (mKeyMatcher == null || mKeyMatcher.matches(tags))
|
||||
&& (mValueMatcher == null || mValueMatcher.matches(tags));
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean matchesWay(Tag[] tags, byte zoomLevel, Closed closed) {
|
||||
boolean matchesWay(Tag[] tags, byte zoomLevel, int closed) {
|
||||
return mZoomMin <= zoomLevel && mZoomMax >= zoomLevel
|
||||
&& (mElementMatcher == null || mElementMatcher.matches(Element.WAY))
|
||||
&& (mClosedMatcher == null || mClosedMatcher.matches(closed))
|
||||
&& (mElement == Element.WAY || mElement == Element.ANY)
|
||||
&& (mClosed == closed || mClosed == Closed.ANY)
|
||||
&& (mKeyMatcher == null || mKeyMatcher.matches(tags))
|
||||
&& (mValueMatcher == null || mValueMatcher.matches(tags));
|
||||
}
|
||||
|
||||
@ -32,15 +32,19 @@ public class RenderTheme {
|
||||
private static final int MATCHING_CACHE_SIZE = 1024;
|
||||
private static final int RENDER_THEME_VERSION = 1;
|
||||
|
||||
private static void validate(String elementName, Integer version, float baseStrokeWidth, float baseTextSize) {
|
||||
private static void validate(String elementName, Integer version,
|
||||
float baseStrokeWidth, float baseTextSize) {
|
||||
if (version == null) {
|
||||
throw new IllegalArgumentException("missing attribute version for element:" + elementName);
|
||||
throw new IllegalArgumentException("missing attribute version for element:"
|
||||
+ elementName);
|
||||
} else if (version.intValue() != RENDER_THEME_VERSION) {
|
||||
throw new IllegalArgumentException("invalid render theme version:" + version);
|
||||
} else if (baseStrokeWidth < 0) {
|
||||
throw new IllegalArgumentException("base-stroke-width must not be negative: " + baseStrokeWidth);
|
||||
throw new IllegalArgumentException("base-stroke-width must not be negative: "
|
||||
+ baseStrokeWidth);
|
||||
} else if (baseTextSize < 0) {
|
||||
throw new IllegalArgumentException("base-text-size must not be negative: " + baseTextSize);
|
||||
throw new IllegalArgumentException("base-text-size must not be negative: "
|
||||
+ baseTextSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,9 +97,12 @@ public class RenderTheme {
|
||||
mBaseTextSize = baseTextSize;
|
||||
mRulesList = new ArrayList<Rule>();
|
||||
|
||||
mMatchingCacheNodes = new LRUCache<MatchingCacheKey, RenderInstruction[]>(MATCHING_CACHE_SIZE);
|
||||
mMatchingCacheWay = new LRUCache<MatchingCacheKey, RenderInstruction[]>(MATCHING_CACHE_SIZE);
|
||||
mMatchingCacheArea = new LRUCache<MatchingCacheKey, RenderInstruction[]>(MATCHING_CACHE_SIZE);
|
||||
mMatchingCacheNodes = new LRUCache<MatchingCacheKey, RenderInstruction[]>(
|
||||
MATCHING_CACHE_SIZE);
|
||||
mMatchingCacheWay = new LRUCache<MatchingCacheKey, RenderInstruction[]>(
|
||||
MATCHING_CACHE_SIZE);
|
||||
mMatchingCacheArea = new LRUCache<MatchingCacheKey, RenderInstruction[]>(
|
||||
MATCHING_CACHE_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,7 +214,8 @@ public class RenderTheme {
|
||||
* @param changed
|
||||
* ...
|
||||
*/
|
||||
public void matchWay(RenderCallback renderCallback, Tag[] tags, byte zoomLevel, boolean closed, boolean changed) {
|
||||
public void matchWay(RenderCallback renderCallback, Tag[] tags, byte zoomLevel,
|
||||
boolean closed, boolean changed) {
|
||||
RenderInstruction[] renderInstructions = null;
|
||||
|
||||
LRUCache<MatchingCacheKey, RenderInstruction[]> matchingCache;
|
||||
@ -241,10 +249,11 @@ public class RenderTheme {
|
||||
}
|
||||
} else {
|
||||
// cache miss
|
||||
Closed c = (closed ? Closed.YES : Closed.NO);
|
||||
int c = (closed ? Closed.YES : Closed.NO);
|
||||
List<RenderInstruction> matchingList = new ArrayList<RenderInstruction>(4);
|
||||
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
||||
mRulesList.get(i).matchWay(renderCallback, tags, zoomLevel, c, matchingList);
|
||||
mRulesList.get(i).matchWay(renderCallback, tags, zoomLevel, c,
|
||||
matchingList);
|
||||
}
|
||||
int size = matchingList.size();
|
||||
if (size > 0) {
|
||||
|
||||
@ -33,21 +33,20 @@ abstract class Rule {
|
||||
private static final Pattern SPLIT_PATTERN = Pattern.compile("\\|");
|
||||
private static final String STRING_NEGATION = "~";
|
||||
private static final String STRING_WILDCARD = "*";
|
||||
private static final String UNKNOWN_ENUM_VALUE = "unknown enum value: ";
|
||||
|
||||
private static Rule createRule(Stack<Rule> ruleStack, Element element, String keys, String values, Closed closed,
|
||||
private static Rule createRule(Stack<Rule> ruleStack, int element, String keys,
|
||||
String values, int closed,
|
||||
byte zoomMin, byte zoomMax) {
|
||||
ElementMatcher elementMatcher = getElementMatcher(element);
|
||||
ClosedMatcher closedMatcher = getClosedMatcher(closed);
|
||||
List<String> keyList = new ArrayList<String>(Arrays.asList(SPLIT_PATTERN.split(keys)));
|
||||
List<String> valueList = new ArrayList<String>(Arrays.asList(SPLIT_PATTERN.split(values)));
|
||||
|
||||
elementMatcher = RuleOptimizer.optimize(elementMatcher, ruleStack);
|
||||
closedMatcher = RuleOptimizer.optimize(closedMatcher, ruleStack);
|
||||
List<String> keyList = new ArrayList<String>(Arrays.asList(SPLIT_PATTERN
|
||||
.split(keys)));
|
||||
List<String> valueList = new ArrayList<String>(Arrays.asList(SPLIT_PATTERN
|
||||
.split(values)));
|
||||
|
||||
if (valueList.remove(STRING_NEGATION)) {
|
||||
AttributeMatcher attributeMatcher = new NegativeMatcher(keyList, valueList);
|
||||
return new NegativeRule(elementMatcher, closedMatcher, zoomMin, zoomMax, attributeMatcher);
|
||||
return new NegativeRule(element, closed, zoomMin, zoomMax,
|
||||
attributeMatcher);
|
||||
}
|
||||
|
||||
AttributeMatcher keyMatcher = getKeyMatcher(keyList);
|
||||
@ -56,33 +55,8 @@ abstract class Rule {
|
||||
keyMatcher = RuleOptimizer.optimize(keyMatcher, ruleStack);
|
||||
valueMatcher = RuleOptimizer.optimize(valueMatcher, ruleStack);
|
||||
|
||||
return new PositiveRule(elementMatcher, closedMatcher, zoomMin, zoomMax, keyMatcher, valueMatcher);
|
||||
}
|
||||
|
||||
private static ClosedMatcher getClosedMatcher(Closed closed) {
|
||||
switch (closed) {
|
||||
case YES:
|
||||
return ClosedWayMatcher.getInstance();
|
||||
case NO:
|
||||
return LinearWayMatcher.getInstance();
|
||||
case ANY:
|
||||
return AnyMatcher.getInstance();
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(UNKNOWN_ENUM_VALUE + closed);
|
||||
}
|
||||
|
||||
private static ElementMatcher getElementMatcher(Element element) {
|
||||
switch (element) {
|
||||
case NODE:
|
||||
return ElementNodeMatcher.getInstance();
|
||||
case WAY:
|
||||
return ElementWayMatcher.getInstance();
|
||||
case ANY:
|
||||
return AnyMatcher.getInstance();
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(UNKNOWN_ENUM_VALUE + element);
|
||||
return new PositiveRule(element, closed, zoomMin, zoomMax,
|
||||
keyMatcher, valueMatcher);
|
||||
}
|
||||
|
||||
private static AttributeMatcher getKeyMatcher(List<String> keyList) {
|
||||
@ -119,28 +93,31 @@ abstract class Rule {
|
||||
return attributeMatcher;
|
||||
}
|
||||
|
||||
private static void validate(String elementName, Element element, String keys, String values, byte zoomMin,
|
||||
byte zoomMax) {
|
||||
if (element == null) {
|
||||
throw new IllegalArgumentException("missing attribute e for element: " + elementName);
|
||||
} else if (keys == null) {
|
||||
throw new IllegalArgumentException("missing attribute k for element: " + elementName);
|
||||
private static void validate(String elementName, String keys, String values,
|
||||
byte zoomMin, byte zoomMax) {
|
||||
if (keys == null) {
|
||||
throw new IllegalArgumentException("missing attribute k for element: "
|
||||
+ elementName);
|
||||
} else if (values == null) {
|
||||
throw new IllegalArgumentException("missing attribute v for element: " + elementName);
|
||||
throw new IllegalArgumentException("missing attribute v for element: "
|
||||
+ elementName);
|
||||
} else if (zoomMin < 0) {
|
||||
throw new IllegalArgumentException("zoom-min must not be negative: " + zoomMin);
|
||||
throw new IllegalArgumentException("zoom-min must not be negative: "
|
||||
+ zoomMin);
|
||||
} else if (zoomMax < 0) {
|
||||
throw new IllegalArgumentException("zoom-max must not be negative: " + zoomMax);
|
||||
throw new IllegalArgumentException("zoom-max must not be negative: "
|
||||
+ zoomMax);
|
||||
} else if (zoomMin > zoomMax) {
|
||||
throw new IllegalArgumentException("zoom-min must be less or equal zoom-max: " + zoomMin);
|
||||
throw new IllegalArgumentException(
|
||||
"zoom-min must be less or equal zoom-max: " + zoomMin);
|
||||
}
|
||||
}
|
||||
|
||||
static Rule create(String elementName, Attributes attributes, Stack<Rule> ruleStack) {
|
||||
Element element = null;
|
||||
int element = Element.ANY;
|
||||
String keys = null;
|
||||
String values = null;
|
||||
Closed closed = Closed.ANY;
|
||||
int closed = Closed.ANY;
|
||||
byte zoomMin = 0;
|
||||
byte zoomMax = Byte.MAX_VALUE;
|
||||
|
||||
@ -149,13 +126,21 @@ abstract class Rule {
|
||||
String value = attributes.getValue(i);
|
||||
|
||||
if ("e".equals(name)) {
|
||||
element = Element.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
String val = value.toUpperCase(Locale.ENGLISH);
|
||||
if ("WAY".equals(val))
|
||||
element = Element.WAY;
|
||||
else if ("NODE".equals(val))
|
||||
element = Element.NODE;
|
||||
} else if ("k".equals(name)) {
|
||||
keys = value;
|
||||
} else if ("v".equals(name)) {
|
||||
values = value;
|
||||
} else if ("closed".equals(name)) {
|
||||
closed = Closed.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
String val = value.toUpperCase(Locale.ENGLISH);
|
||||
if ("YES".equals(val))
|
||||
closed = Closed.YES;
|
||||
else if ("NO".equals(val))
|
||||
closed = Closed.NO;
|
||||
} else if ("zoom-min".equals(name)) {
|
||||
zoomMin = Byte.parseByte(value);
|
||||
} else if ("zoom-max".equals(name)) {
|
||||
@ -165,7 +150,7 @@ abstract class Rule {
|
||||
}
|
||||
}
|
||||
|
||||
validate(elementName, element, keys, values, zoomMin, zoomMax);
|
||||
validate(elementName, keys, values, zoomMin, zoomMax);
|
||||
return createRule(ruleStack, element, keys, values, closed, zoomMin, zoomMax);
|
||||
}
|
||||
|
||||
@ -175,22 +160,16 @@ abstract class Rule {
|
||||
private Rule[] mSubRuleArray;
|
||||
private RenderInstruction[] mRenderInstructionArray;
|
||||
|
||||
final ClosedMatcher mClosedMatcher;
|
||||
final ElementMatcher mElementMatcher;
|
||||
final byte mZoomMax;
|
||||
final byte mZoomMin;
|
||||
final int mElement;
|
||||
final int mClosed;
|
||||
|
||||
Rule(ElementMatcher elementMatcher, ClosedMatcher closedMatcher, byte zoomMin, byte zoomMax) {
|
||||
if (elementMatcher instanceof AnyMatcher)
|
||||
mElementMatcher = null;
|
||||
else
|
||||
mElementMatcher = elementMatcher;
|
||||
|
||||
if (closedMatcher instanceof AnyMatcher)
|
||||
mClosedMatcher = null;
|
||||
else
|
||||
mClosedMatcher = closedMatcher;
|
||||
Rule(int element, int closed, byte zoomMin,
|
||||
byte zoomMax) {
|
||||
|
||||
mClosed = closed;
|
||||
mElement = element;
|
||||
mZoomMin = zoomMin;
|
||||
mZoomMax = zoomMax;
|
||||
|
||||
@ -208,7 +187,7 @@ abstract class Rule {
|
||||
|
||||
abstract boolean matchesNode(Tag[] tags, byte zoomLevel);
|
||||
|
||||
abstract boolean matchesWay(Tag[] tags, byte zoomLevel, Closed closed);
|
||||
abstract boolean matchesWay(Tag[] tags, byte zoomLevel, int closed);
|
||||
|
||||
void matchNode(RenderCallback renderCallback, Tag[] tags, byte zoomLevel) {
|
||||
if (matchesNode(tags, zoomLevel)) {
|
||||
@ -221,7 +200,8 @@ abstract class Rule {
|
||||
}
|
||||
}
|
||||
|
||||
void matchWay(RenderCallback renderCallback, Tag[] tags, byte zoomLevel, Closed closed,
|
||||
void matchWay(RenderCallback renderCallback, Tag[] tags, byte zoomLevel,
|
||||
int closed,
|
||||
List<RenderInstruction> matchingList) {
|
||||
|
||||
if (matchesWay(tags, zoomLevel, closed)) {
|
||||
@ -229,7 +209,8 @@ abstract class Rule {
|
||||
matchingList.add(mRenderInstructionArray[i]);
|
||||
|
||||
for (int i = 0, n = mSubRuleArray.length; i < n; i++)
|
||||
mSubRuleArray[i].matchWay(renderCallback, tags, zoomLevel, closed, matchingList);
|
||||
mSubRuleArray[i].matchWay(renderCallback, tags, zoomLevel, closed,
|
||||
matchingList);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,11 +20,13 @@ import java.util.logging.Logger;
|
||||
final class RuleOptimizer {
|
||||
private static final Logger LOG = Logger.getLogger(RuleOptimizer.class.getName());
|
||||
|
||||
private static AttributeMatcher optimizeKeyMatcher(AttributeMatcher attributeMatcher, Stack<Rule> ruleStack) {
|
||||
private static AttributeMatcher optimizeKeyMatcher(AttributeMatcher attributeMatcher,
|
||||
Stack<Rule> ruleStack) {
|
||||
for (int i = 0, n = ruleStack.size(); i < n; ++i) {
|
||||
if (ruleStack.get(i) instanceof PositiveRule) {
|
||||
PositiveRule positiveRule = (PositiveRule) ruleStack.get(i);
|
||||
if (positiveRule.mKeyMatcher != null && positiveRule.mKeyMatcher.isCoveredBy(attributeMatcher)) {
|
||||
if (positiveRule.mKeyMatcher != null
|
||||
&& positiveRule.mKeyMatcher.isCoveredBy(attributeMatcher)) {
|
||||
return null; // AnyMatcher.getInstance();
|
||||
}
|
||||
}
|
||||
@ -33,12 +35,14 @@ final class RuleOptimizer {
|
||||
return attributeMatcher;
|
||||
}
|
||||
|
||||
private static AttributeMatcher optimizeValueMatcher(AttributeMatcher attributeMatcher, Stack<Rule> ruleStack) {
|
||||
private static AttributeMatcher optimizeValueMatcher(
|
||||
AttributeMatcher attributeMatcher, Stack<Rule> ruleStack) {
|
||||
for (int i = 0, n = ruleStack.size(); i < n; ++i) {
|
||||
if (ruleStack.get(i) instanceof PositiveRule) {
|
||||
PositiveRule positiveRule = (PositiveRule) ruleStack.get(i);
|
||||
|
||||
if (positiveRule.mValueMatcher != null && positiveRule.mValueMatcher.isCoveredBy(attributeMatcher)) {
|
||||
if (positiveRule.mValueMatcher != null
|
||||
&& positiveRule.mValueMatcher.isCoveredBy(attributeMatcher)) {
|
||||
return null; // AnyMatcher.getInstance();
|
||||
}
|
||||
}
|
||||
@ -47,7 +51,8 @@ final class RuleOptimizer {
|
||||
return attributeMatcher;
|
||||
}
|
||||
|
||||
static AttributeMatcher optimize(AttributeMatcher attributeMatcher, Stack<Rule> ruleStack) {
|
||||
static AttributeMatcher optimize(AttributeMatcher attributeMatcher,
|
||||
Stack<Rule> ruleStack) {
|
||||
if (attributeMatcher instanceof AnyMatcher)
|
||||
return attributeMatcher;// return null;
|
||||
else if (attributeMatcher instanceof NegativeMatcher) {
|
||||
@ -61,60 +66,61 @@ final class RuleOptimizer {
|
||||
} else if (attributeMatcher instanceof MultiValueMatcher) {
|
||||
return optimizeValueMatcher(attributeMatcher, ruleStack);
|
||||
}
|
||||
throw new IllegalArgumentException("unknown AttributeMatcher: " + attributeMatcher);
|
||||
throw new IllegalArgumentException("unknown AttributeMatcher: "
|
||||
+ attributeMatcher);
|
||||
}
|
||||
|
||||
static ClosedMatcher optimize(ClosedMatcher closedMatcher, Stack<Rule> ruleStack) {
|
||||
if (closedMatcher == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (closedMatcher instanceof AnyMatcher) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0, n = ruleStack.size(); i < n; ++i) {
|
||||
ClosedMatcher matcher = ruleStack.get(i).mClosedMatcher;
|
||||
if (matcher == null)
|
||||
return null;
|
||||
|
||||
if (matcher.isCoveredBy(closedMatcher)) {
|
||||
return null; // AnyMatcher.getInstance();
|
||||
|
||||
} else if (!closedMatcher.isCoveredBy(ruleStack.get(i).mClosedMatcher)) {
|
||||
LOG.warning("unreachable rule (closed)");
|
||||
}
|
||||
}
|
||||
|
||||
return closedMatcher;
|
||||
}
|
||||
|
||||
static ElementMatcher optimize(ElementMatcher elementMatcher, Stack<Rule> ruleStack) {
|
||||
|
||||
if (elementMatcher == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (elementMatcher instanceof AnyMatcher) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0, n = ruleStack.size(); i < n; ++i) {
|
||||
ElementMatcher matcher = ruleStack.get(i).mElementMatcher;
|
||||
|
||||
if (matcher == null)
|
||||
return null;
|
||||
|
||||
if (matcher.isCoveredBy(elementMatcher)) {
|
||||
return null; // AnyMatcher.getInstance();
|
||||
|
||||
} else if (!elementMatcher.isCoveredBy(ruleStack.get(i).mElementMatcher)) {
|
||||
LOG.warning("unreachable rule (e)");
|
||||
}
|
||||
}
|
||||
|
||||
return elementMatcher;
|
||||
}
|
||||
// static ClosedMatcher optimize(ClosedMatcher closedMatcher, Stack<Rule> ruleStack) {
|
||||
// if (closedMatcher == null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// if (closedMatcher instanceof AnyMatcher) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// for (int i = 0, n = ruleStack.size(); i < n; ++i) {
|
||||
// ClosedMatcher matcher = ruleStack.get(i).mClosedMatcher;
|
||||
// if (matcher == null)
|
||||
// return null;
|
||||
//
|
||||
// if (matcher.isCoveredBy(closedMatcher)) {
|
||||
// return null; // AnyMatcher.getInstance();
|
||||
//
|
||||
// } else if (!closedMatcher.isCoveredBy(ruleStack.get(i).mClosedMatcher)) {
|
||||
// LOG.warning("unreachable rule (closed)");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return closedMatcher;
|
||||
// }
|
||||
//
|
||||
// static ElementMatcher optimize(ElementMatcher elementMatcher, Stack<Rule> ruleStack) {
|
||||
//
|
||||
// if (elementMatcher == null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// if (elementMatcher instanceof AnyMatcher) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// for (int i = 0, n = ruleStack.size(); i < n; ++i) {
|
||||
// ElementMatcher matcher = ruleStack.get(i).mElementMatcher;
|
||||
//
|
||||
// if (matcher == null)
|
||||
// return null;
|
||||
//
|
||||
// if (matcher.isCoveredBy(elementMatcher)) {
|
||||
// return null; // AnyMatcher.getInstance();
|
||||
//
|
||||
// } else if (!elementMatcher.isCoveredBy(ruleStack.get(i).mElementMatcher)) {
|
||||
// LOG.warning("unreachable rule (e)");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return elementMatcher;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from other classes.
|
||||
|
||||
@ -8,9 +8,17 @@
|
||||
<rule e="way" k="*" v="*">
|
||||
|
||||
<!-- landuse -->
|
||||
<rule e="way" k="landuse" v="*" zoom-min="10">
|
||||
<rule e="way" k="landuse" v="residential|farmyard|retail|commercial">
|
||||
<area fill="#ededec" fade="10" />
|
||||
<rule e="way" k="landuse" v="*">
|
||||
<rule e="way" k="*" zoom-min="12" v="farmland|farm">
|
||||
<area fill="#fff8bf" fade="12" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="landuse" v="grass">
|
||||
<area fill="#deecb9" fade="12" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" zoom-min="10" v="residential|farmyard|retail|commercial">
|
||||
<area fill="#efefeb" fade="10" />
|
||||
</rule>
|
||||
|
||||
<!-- <rule e="way" k="landuse" v="industrial|brownfield|railway"> <area
|
||||
@ -19,9 +27,7 @@
|
||||
stroke="#e4e4e4" stroke-width="0.2" /> </rule> -->
|
||||
<!-- <rule e="way" k="landuse" v="garages"> <area fill="#d6d6e4" /> </rule> -->
|
||||
|
||||
<rule e="way" k="landuse" v="grass">
|
||||
<area fill="#deecb9" fade="12" />
|
||||
</rule>
|
||||
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="outline" v="*">
|
||||
@ -103,9 +109,7 @@
|
||||
<rule e="way" k="*" v="meadow|scrub">
|
||||
<area fill="#deecb9" fade="12" />
|
||||
</rule>
|
||||
<rule e="way" k="*" v="farmland|farm">
|
||||
<area fill="#fff8bf" fade="12" />
|
||||
</rule>
|
||||
|
||||
<!-- <rule e="way" k="*" v="village_green|recreation_ground">
|
||||
<area fill="#daebaf" fade="12" />
|
||||
</rule> -->
|
||||
@ -130,9 +134,14 @@
|
||||
</rule>
|
||||
|
||||
|
||||
<rule e="way" k="natural|landuse" v="forest|wood" zoom-min="10">
|
||||
<rule e="way" k="natural|landuse" v="forest|wood" zoom-min="9">
|
||||
<!-- <area fill="#BCCBB0" fade="10" /> -->
|
||||
<area fill="#cde2bc" fade="10" />
|
||||
<!-- <rule e="way" k="*" v="*" zoom-max="11"> -->
|
||||
<area fill="#d3dec8" fade="9" />
|
||||
<!-- </rule> -->
|
||||
<!-- <rule e="way" k="*" v="*" zoom-min="12">
|
||||
<area fill="#cde2bc" fade="12" />
|
||||
</rule> -->
|
||||
<!-- <area fill="#87a670" fade="10" /> -->
|
||||
</rule>
|
||||
|
||||
@ -169,8 +178,8 @@
|
||||
<area fill="#fcfeab" />
|
||||
</rule>
|
||||
<!-- Heideland -->
|
||||
<rule e="way" k="*" v="heath">
|
||||
<area fill="#ffffc0" fade="10" />
|
||||
<rule e="way" k="*" zoom-min="12" v="heath">
|
||||
<area fill="#ffffc0" fade="12" />
|
||||
</rule>
|
||||
<rule e="way" k="*" v="marsh|wetland">
|
||||
<area fill="#deecb9" fade="12" />
|
||||
@ -207,7 +216,8 @@
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="natural" v="water">
|
||||
<area fill="#b4cbdc" />
|
||||
<line stroke="#eea4bbcc" fixed="true" stroke-width="1.4" stroke-linecap="butt" />
|
||||
<area fill="#b4cbdc" />
|
||||
</rule>
|
||||
|
||||
<!-- waterways -->
|
||||
@ -232,6 +242,7 @@
|
||||
fixed="true" />
|
||||
</rule>
|
||||
<rule e="way" k="waterway" v="riverbank|dock">
|
||||
<line stroke="#eea4bbcc" fixed="true" stroke-width="1.4" stroke-linecap="butt" />
|
||||
<area fill="#b4cbdc" />
|
||||
</rule>
|
||||
<rule e="way" k="waterway" v="weir">
|
||||
@ -323,9 +334,8 @@
|
||||
</rule>-->
|
||||
|
||||
<rule e="way" k="*" v="*" zoom-min="15">
|
||||
<line stroke="#c9c3c3" stroke-width="0.6" fixed="true"
|
||||
stroke-linecap="butt" />
|
||||
<area fill="#e9e6e6" fade="15" />
|
||||
<line stroke="#c9c3c1" stroke-width="0.6" fixed="true" stroke-linecap="butt" />
|
||||
<area fill="#e9e6e3" fade="15" />
|
||||
</rule>
|
||||
|
||||
<!-- <rule e="way" k="*" v="*" zoom-min="17">
|
||||
@ -359,31 +369,31 @@
|
||||
<rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
|
||||
|
||||
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
|
||||
<!-- <line stroke="#eeee4a" stroke-width="1.3" stroke-linecap="butt"
|
||||
<!-- <line stroke="#eeee4a" stroke-width="1.8" stroke-linecap="butt"
|
||||
fixed="true" /> -->
|
||||
<line stroke="#f2df6d" stroke-width="1.2" stroke-linecap="butt"
|
||||
<line stroke="#f2df6d" stroke-width="1.7" stroke-linecap="butt"
|
||||
fixed="true" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
|
||||
<line stroke="#fed6a3" stroke-width="1.4" stroke-linecap="butt"
|
||||
<line stroke="#fed6a3" stroke-width="1.9" stroke-linecap="butt"
|
||||
fixed="true" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" v="primary" zoom-min="8">
|
||||
<rule e="way" k="*" v="primary" zoom-min="7">
|
||||
<!-- <line stroke="#eeee4a" stroke-width="1.4" stroke-linecap="butt"
|
||||
fixed="true" /> -->
|
||||
<line stroke="#f2df6d" stroke-width="1.4" stroke-linecap="butt"
|
||||
<line stroke="#f2df6d" stroke-width="1.9" stroke-linecap="butt"
|
||||
fixed="true" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" v="trunk" zoom-min="8">
|
||||
<line stroke="#fed6a3" stroke-width="1.4" stroke-linecap="butt"
|
||||
<rule e="way" k="*" v="trunk" zoom-min="7">
|
||||
<line stroke="#fed6a3" stroke-width="1.9" stroke-linecap="butt"
|
||||
fixed="true" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" v="motorway">
|
||||
<line stroke="#eec693" stroke-width="1.5" stroke-linecap="butt"
|
||||
<line stroke="#eec693" stroke-width="2.0" stroke-linecap="butt"
|
||||
fixed="true" />
|
||||
</rule>
|
||||
</rule>
|
||||
|
||||
@ -47,7 +47,8 @@ public final class Line implements RenderInstruction {
|
||||
* @throws IOException
|
||||
* if an I/O error occurs while reading a resource.
|
||||
*/
|
||||
public static Line create(String elementName, Attributes attributes, int level) throws IOException {
|
||||
public static Line create(String elementName, Attributes attributes, int level)
|
||||
throws IOException {
|
||||
String src = null;
|
||||
int stroke = Color.BLACK;
|
||||
float strokeWidth = 0;
|
||||
@ -83,12 +84,14 @@ public final class Line implements RenderInstruction {
|
||||
}
|
||||
|
||||
validate(strokeWidth);
|
||||
return new Line(src, stroke, strokeWidth, strokeDasharray, strokeLinecap, level, outline, fixed);
|
||||
return new Line(src, stroke, strokeWidth, strokeDasharray, strokeLinecap, level,
|
||||
outline, fixed);
|
||||
}
|
||||
|
||||
private static void validate(float strokeWidth) {
|
||||
if (strokeWidth < 0) {
|
||||
throw new IllegalArgumentException("stroke-width must not be negative: " + strokeWidth);
|
||||
throw new IllegalArgumentException("stroke-width must not be negative: "
|
||||
+ strokeWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +134,8 @@ public final class Line implements RenderInstruction {
|
||||
*/
|
||||
public final boolean fixed;
|
||||
|
||||
private Line(String src, int stroke, float strokeWidth, float[] strokeDasharray, Cap strokeLinecap, int level,
|
||||
private Line(String src, int stroke, float strokeWidth, float[] strokeDasharray,
|
||||
Cap strokeLinecap, int level,
|
||||
int outline, boolean fixed)
|
||||
throws IOException {
|
||||
super();
|
||||
@ -146,7 +150,7 @@ public final class Line implements RenderInstruction {
|
||||
paint.setPathEffect(new DashPathEffect(strokeDasharray, 0));
|
||||
}
|
||||
paint.setStrokeCap(strokeLinecap);
|
||||
round = strokeLinecap == Cap.ROUND;
|
||||
round = (strokeLinecap == Cap.ROUND);
|
||||
this.color = stroke;
|
||||
this.strokeWidth = strokeWidth;
|
||||
this.level = level;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user