simplify rendertheme 'closed' and 'element' matching

This commit is contained in:
Hannes Janetzek 2012-07-10 09:00:45 +02:00
parent 380b5e019d
commit b410059282
16 changed files with 195 additions and 402 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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>

View File

@ -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;