- extract interface of RenderTheme
- pass MapElement to RenderTheme - refactor: join duplicated code for node and way matching
This commit is contained in:
parent
7d767ec2e4
commit
bcb529906a
@ -35,7 +35,7 @@ import org.oscim.renderer.layer.LineTexLayer;
|
|||||||
import org.oscim.renderer.layer.PolygonLayer;
|
import org.oscim.renderer.layer.PolygonLayer;
|
||||||
import org.oscim.renderer.layer.TextItem;
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.theme.IRenderCallback;
|
import org.oscim.theme.IRenderCallback;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.IRenderTheme;
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
import org.oscim.theme.renderinstruction.Circle;
|
import org.oscim.theme.renderinstruction.Circle;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
@ -80,7 +80,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
private static DebugSettings debug;
|
private static DebugSettings debug;
|
||||||
|
|
||||||
private RenderTheme renderTheme;
|
private IRenderTheme renderTheme;
|
||||||
private int renderLevels;
|
private int renderLevels;
|
||||||
|
|
||||||
// current MapDatabase used by this TileGenerator
|
// current MapDatabase used by this TileGenerator
|
||||||
@ -106,7 +106,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
private final LineClipper mClipper;
|
private final LineClipper mClipper;
|
||||||
|
|
||||||
public void setRenderTheme(RenderTheme theme) {
|
public void setRenderTheme(IRenderTheme theme) {
|
||||||
renderTheme = theme;
|
renderTheme = theme;
|
||||||
renderLevels = theme.getLevels();
|
renderLevels = theme.getLevels();
|
||||||
}
|
}
|
||||||
@ -182,20 +182,20 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug.drawTileFrames) {
|
// if (debug.drawTileFrames) {
|
||||||
// draw tile coordinate
|
// // draw tile coordinate
|
||||||
mTagName = new Tag("name", mTile.toString(), false);
|
// mTagName = new Tag("name", mTile.toString(), false);
|
||||||
mElement = mDebugPoint;
|
// mElement = mDebugPoint;
|
||||||
RenderInstruction[] ri;
|
// RenderInstruction[] ri;
|
||||||
ri = renderTheme.matchNode(debugTagWay, (byte) 0);
|
// ri = renderTheme.matchNode(debugTagWay, (byte) 0);
|
||||||
renderNode(ri);
|
// renderNode(ri);
|
||||||
|
//
|
||||||
// draw tile box
|
// // draw tile box
|
||||||
mElement = mDebugWay;
|
// mElement = mDebugWay;
|
||||||
mDrawingLayer = 100 * renderLevels;
|
// mDrawingLayer = 100 * renderLevels;
|
||||||
ri = renderTheme.matchWay(mDebugWay.tags, (byte) 0, false);
|
// ri = renderTheme.matchWay(mDebugWay.tags, (byte) 0, false);
|
||||||
renderWay(ri);
|
// renderWay(ri);
|
||||||
}
|
// }
|
||||||
|
|
||||||
mTile = null;
|
mTile = null;
|
||||||
return true;
|
return true;
|
||||||
@ -281,7 +281,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
filterTags(element.tags);
|
filterTags(element.tags);
|
||||||
|
|
||||||
// get render instructions
|
// get render instructions
|
||||||
RenderInstruction[] ri = renderTheme.matchNode(element.tags, mTile.zoomLevel);
|
//RenderInstruction[] ri = renderTheme.matchNode(element.tags, mTile.zoomLevel);
|
||||||
|
RenderInstruction[] ri = renderTheme.matchElement(element, mTile.zoomLevel);
|
||||||
|
|
||||||
if (ri != null)
|
if (ri != null)
|
||||||
renderNode(ri);
|
renderNode(ri);
|
||||||
@ -297,8 +298,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
mDrawingLayer = getValidLayer(element.layer) * renderLevels;
|
mDrawingLayer = getValidLayer(element.layer) * renderLevels;
|
||||||
|
|
||||||
// get render instructions
|
// get render instructions
|
||||||
RenderInstruction[] ri = renderTheme.matchWay(element.tags,
|
// RenderInstruction[] ri = renderTheme.matchWay(element.tags,
|
||||||
(byte) (mTile.zoomLevel + 0), closed);
|
// (byte) (mTile.zoomLevel + 0), closed);
|
||||||
|
|
||||||
|
RenderInstruction[] ri = renderTheme.matchElement(element, mTile.zoomLevel);
|
||||||
|
|
||||||
renderWay(ri);
|
renderWay(ri);
|
||||||
|
|
||||||
@ -314,15 +317,15 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
private void debugUnmatched(boolean closed, Tag[] tags) {
|
private void debugUnmatched(boolean closed, Tag[] tags) {
|
||||||
Log.d(TAG, "DBG way not matched: " + closed + " "
|
Log.d(TAG, "DBG way not matched: " + closed + " "
|
||||||
+ Arrays.deepToString(tags));
|
+ Arrays.deepToString(tags));
|
||||||
|
mElement = null;
|
||||||
mTagName = new Tag("name", tags[0].key + ":"
|
// mTagName = new Tag("name", tags[0].key + ":"
|
||||||
+ tags[0].value, false);
|
// + tags[0].value, false);
|
||||||
|
//
|
||||||
RenderInstruction[] ri;
|
// RenderInstruction[] ri;
|
||||||
ri = renderTheme.matchWay(closed ? debugTagArea : debugTagWay,
|
// ri = renderTheme.matchWay(closed ? debugTagArea : debugTagWay,
|
||||||
(byte) 0, true);
|
// (byte) 0, true);
|
||||||
|
//
|
||||||
renderWay(ri);
|
// renderWay(ri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderWay(RenderInstruction[] ri) {
|
private void renderWay(RenderInstruction[] ri) {
|
||||||
|
|||||||
@ -32,8 +32,8 @@ import org.oscim.database.MapOptions;
|
|||||||
import org.oscim.layers.Layer;
|
import org.oscim.layers.Layer;
|
||||||
import org.oscim.renderer.GLRenderer;
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.theme.ExternalRenderTheme;
|
import org.oscim.theme.ExternalRenderTheme;
|
||||||
|
import org.oscim.theme.IRenderTheme;
|
||||||
import org.oscim.theme.InternalRenderTheme;
|
import org.oscim.theme.InternalRenderTheme;
|
||||||
import org.oscim.theme.RenderTheme;
|
|
||||||
import org.oscim.theme.RenderThemeHandler;
|
import org.oscim.theme.RenderThemeHandler;
|
||||||
import org.oscim.theme.Theme;
|
import org.oscim.theme.Theme;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
@ -263,7 +263,7 @@ public class TileLayer extends Layer {
|
|||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
try {
|
try {
|
||||||
inputStream = theme.getRenderThemeAsStream();
|
inputStream = theme.getRenderThemeAsStream();
|
||||||
RenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
|
IRenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
|
||||||
t.scaleTextSize(1 + (MapView.dpi / 240 - 1) * 0.5f);
|
t.scaleTextSize(1 + (MapView.dpi / 240 - 1) * 0.5f);
|
||||||
|
|
||||||
// FIXME !!!
|
// FIXME !!!
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import org.oscim.core.Tile;
|
|||||||
import org.oscim.layers.tile.MapTile;
|
import org.oscim.layers.tile.MapTile;
|
||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.renderer.overlays.RenderOverlay;
|
import org.oscim.renderer.overlays.RenderOverlay;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.IRenderTheme;
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.utils.Matrix4;
|
import org.oscim.utils.Matrix4;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
@ -124,7 +124,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mFillCoords[7] = min;
|
mFillCoords[7] = min;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setRenderTheme(RenderTheme t) {
|
public static void setRenderTheme(IRenderTheme t) {
|
||||||
mClearColor = GlUtils.colorToFloat(t.getMapBackground());
|
mClearColor = GlUtils.colorToFloat(t.getMapBackground());
|
||||||
mUpdateColor = true;
|
mUpdateColor = true;
|
||||||
}
|
}
|
||||||
|
|||||||
66
src/org/oscim/theme/IRenderTheme.java
Normal file
66
src/org/oscim/theme/IRenderTheme.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
|
* Copyright 2013 Hannes Janetzek
|
||||||
|
*
|
||||||
|
* 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.oscim.theme;
|
||||||
|
|
||||||
|
import org.oscim.core.MapElement;
|
||||||
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
|
|
||||||
|
public interface IRenderTheme {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a MapElement with the given parameters against this RenderTheme.
|
||||||
|
*
|
||||||
|
* @param zoomLevel
|
||||||
|
* the zoom level at which the way should be matched.
|
||||||
|
* @return matching render instructions
|
||||||
|
*/
|
||||||
|
public abstract RenderInstruction[] matchElement(MapElement element, int zoomLevel);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called when this RenderTheme gets destroyed to clean up and free
|
||||||
|
* resources.
|
||||||
|
*/
|
||||||
|
public abstract void destroy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the number of distinct drawing levels required by this
|
||||||
|
* RenderTheme.
|
||||||
|
*/
|
||||||
|
public abstract int getLevels();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the map background color of this RenderTheme.
|
||||||
|
*/
|
||||||
|
public abstract int getMapBackground();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales the stroke width of this RenderTheme by the given factor.
|
||||||
|
*
|
||||||
|
* @param scaleFactor
|
||||||
|
* the factor by which the stroke width should be scaled.
|
||||||
|
*/
|
||||||
|
public abstract void scaleStrokeWidth(float scaleFactor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales the text size of this RenderTheme by the given factor.
|
||||||
|
*
|
||||||
|
* @param scaleFactor
|
||||||
|
* the factor by which the text size should be scaled.
|
||||||
|
*/
|
||||||
|
public abstract void scaleTextSize(float scaleFactor);
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,10 +14,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.theme;
|
package org.oscim.theme;
|
||||||
|
|
||||||
|
import static org.oscim.core.MapElement.GEOM_LINE;
|
||||||
|
import static org.oscim.core.MapElement.GEOM_POLY;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.MapElement;
|
||||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
import org.oscim.theme.rule.Closed;
|
import org.oscim.theme.rule.Closed;
|
||||||
import org.oscim.theme.rule.Rule;
|
import org.oscim.theme.rule.Rule;
|
||||||
@ -25,12 +28,13 @@ import org.oscim.utils.LRUCache;
|
|||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A RenderTheme defines how ways and nodes are drawn.
|
* A RenderTheme defines how map elements are drawn.
|
||||||
*/
|
*/
|
||||||
public class RenderTheme {
|
public class RenderTheme implements IRenderTheme {
|
||||||
//private final static String TAG = RenderTheme.class.getName();
|
private final static String TAG = RenderTheme.class.getName();
|
||||||
|
|
||||||
private static final int MATCHING_CACHE_SIZE = 512;
|
private static final int MATCHING_CACHE_SIZE = 512;
|
||||||
private static final int RENDER_THEME_VERSION = 1;
|
private static final int RENDER_THEME_VERSION = 1;
|
||||||
@ -82,25 +86,26 @@ public class RenderTheme {
|
|||||||
|
|
||||||
private final float mBaseStrokeWidth;
|
private final float mBaseStrokeWidth;
|
||||||
private final float mBaseTextSize;
|
private final float mBaseTextSize;
|
||||||
private int mLevels;
|
|
||||||
private final int mMapBackground;
|
private final int mMapBackground;
|
||||||
private final ArrayList<Rule> mRulesList;
|
|
||||||
|
|
||||||
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mNodesCache;
|
private int mLevels;
|
||||||
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mWayCache;
|
private Rule[] mRules;
|
||||||
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mAreaCache;
|
|
||||||
|
|
||||||
private final MatchingCacheKey mAreaCacheKey;
|
class ElementCache {
|
||||||
private final MatchingCacheKey mWayCacheKey;
|
final LRUCache<MatchingCacheKey, RenderInstructionItem> cache;
|
||||||
private final MatchingCacheKey mNodeCacheKey;
|
final MatchingCacheKey cacheKey;
|
||||||
|
|
||||||
private final ArrayList<RenderInstruction> mWayInstructionList;
|
/* temporary matching instructions list */
|
||||||
private final ArrayList<RenderInstruction> mAreaInstructionList;
|
final ArrayList<RenderInstruction> instructionList;
|
||||||
private final ArrayList<RenderInstruction> mNodeInstructionList;
|
|
||||||
|
|
||||||
private RenderInstructionItem mPrevAreaItem;
|
RenderInstructionItem prevItem;
|
||||||
private RenderInstructionItem mPrevWayItem;
|
|
||||||
private RenderInstructionItem mPrevNodeItem;
|
public ElementCache() {
|
||||||
|
cache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(MATCHING_CACHE_SIZE);
|
||||||
|
instructionList = new ArrayList<RenderInstruction>(4);
|
||||||
|
cacheKey = new MatchingCacheKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class RenderInstructionItem {
|
class RenderInstructionItem {
|
||||||
RenderInstructionItem next;
|
RenderInstructionItem next;
|
||||||
@ -109,65 +114,60 @@ public class RenderTheme {
|
|||||||
MatchingCacheKey key;
|
MatchingCacheKey key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ElementCache[] mElementCache;
|
||||||
|
|
||||||
RenderTheme(int mapBackground, float baseStrokeWidth, float baseTextSize) {
|
RenderTheme(int mapBackground, float baseStrokeWidth, float baseTextSize) {
|
||||||
mMapBackground = mapBackground;
|
mMapBackground = mapBackground;
|
||||||
mBaseStrokeWidth = baseStrokeWidth;
|
mBaseStrokeWidth = baseStrokeWidth;
|
||||||
mBaseTextSize = baseTextSize;
|
mBaseTextSize = baseTextSize;
|
||||||
mRulesList = new ArrayList<Rule>();
|
|
||||||
|
|
||||||
mNodesCache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(MATCHING_CACHE_SIZE);
|
mElementCache = new ElementCache[3];
|
||||||
mWayCache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(MATCHING_CACHE_SIZE);
|
for (int i = 0; i < 3; i++)
|
||||||
mAreaCache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(MATCHING_CACHE_SIZE);
|
mElementCache[i] = new ElementCache();
|
||||||
|
|
||||||
mWayInstructionList = new ArrayList<RenderInstruction>(4);
|
|
||||||
mAreaInstructionList = new ArrayList<RenderInstruction>(4);
|
|
||||||
mNodeInstructionList = new ArrayList<RenderInstruction>(4);
|
|
||||||
|
|
||||||
mAreaCacheKey = new MatchingCacheKey();
|
|
||||||
mWayCacheKey = new MatchingCacheKey();
|
|
||||||
mNodeCacheKey = new MatchingCacheKey();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Must be called when this RenderTheme gets destroyed to clean up and free
|
* (non-Javadoc)
|
||||||
* resources.
|
* @see org.oscim.theme.IRenderTheme#destroy()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
mNodesCache.clear();
|
|
||||||
mAreaCache.clear();
|
|
||||||
mWayCache.clear();
|
|
||||||
|
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
for (int i = 0; i < 3; i++)
|
||||||
mRulesList.get(i).onDestroy();
|
mElementCache[i].cache.clear();
|
||||||
|
|
||||||
|
if (mRules != null) {
|
||||||
|
for (int i = 0, n = mRules.length; i < n; i++)
|
||||||
|
mRules[i].onDestroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @return the number of distinct drawing levels required by this
|
* (non-Javadoc)
|
||||||
* RenderTheme.
|
* @see org.oscim.theme.IRenderTheme#getLevels()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int getLevels() {
|
public int getLevels() {
|
||||||
return mLevels;
|
return mLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @return the map background color of this RenderTheme.
|
* (non-Javadoc)
|
||||||
* @see Color
|
* @see org.oscim.theme.IRenderTheme#getMapBackground()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int getMapBackground() {
|
public int getMapBackground() {
|
||||||
return mMapBackground;
|
return mMapBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* ...
|
* (non-Javadoc)
|
||||||
*
|
* @see org.oscim.theme.IRenderTheme#matchWay(org.oscim.core.Tag[], byte,
|
||||||
* @param tags
|
* boolean)
|
||||||
* ...
|
|
||||||
* @param zoomLevel
|
|
||||||
* ...
|
|
||||||
* @return ...
|
|
||||||
*/
|
*/
|
||||||
public RenderInstruction[] matchNode(Tag[] tags, byte zoomLevel) {
|
@Override
|
||||||
|
public RenderInstruction[] matchElement(MapElement element, int zoomLevel) {
|
||||||
|
|
||||||
// list of renderinsctruction items in cache
|
// list of renderinsctruction items in cache
|
||||||
RenderInstructionItem ris = null;
|
RenderInstructionItem ris = null;
|
||||||
@ -175,157 +175,32 @@ public class RenderTheme {
|
|||||||
// the item matching tags and zoomlevel
|
// the item matching tags and zoomlevel
|
||||||
RenderInstructionItem ri = null;
|
RenderInstructionItem ri = null;
|
||||||
|
|
||||||
synchronized (mNodesCache) {
|
int type = element.geometryType;
|
||||||
|
if (type < 1 || type > 3) {
|
||||||
|
Log.d(TAG, "invalid geometry type for RenderTheme " + type);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementCache cache = mElementCache[type - 1];
|
||||||
|
|
||||||
|
// NOTE: maximum zoom level supported is 32
|
||||||
int zoomMask = 1 << zoomLevel;
|
int zoomMask = 1 << zoomLevel;
|
||||||
|
|
||||||
MatchingCacheKey cacheKey = mNodeCacheKey;
|
synchronized (cache) {
|
||||||
if (mPrevNodeItem == null || (mPrevNodeItem.zoom & zoomMask) == 0) {
|
|
||||||
|
if (cache.prevItem == null || (cache.prevItem.zoom & zoomMask) == 0) {
|
||||||
// previous instructions zoom does not match
|
// previous instructions zoom does not match
|
||||||
cacheKey.set(tags, null);
|
cache.cacheKey.set(element.tags, null);
|
||||||
} else {
|
} else {
|
||||||
// compare if tags match previous instructions
|
// compare if tags match previous instructions
|
||||||
if (cacheKey.set(tags, mPrevNodeItem.key))
|
if (cache.cacheKey.set(element.tags, cache.prevItem.key)) {
|
||||||
ri = mPrevNodeItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri == null) {
|
|
||||||
boolean found = mNodesCache.containsKey(cacheKey);
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
ris = mNodesCache.get(cacheKey);
|
|
||||||
|
|
||||||
for (ri = ris; ri != null; ri = ri.next)
|
|
||||||
if ((ri.zoom & zoomMask) != 0)
|
|
||||||
// cache hit
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri == null) {
|
|
||||||
// cache miss
|
|
||||||
List<RenderInstruction> matches = mNodeInstructionList;
|
|
||||||
matches.clear();
|
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i)
|
|
||||||
mRulesList.get(i).matchNode(tags, zoomLevel, matches);
|
|
||||||
|
|
||||||
int size = matches.size();
|
|
||||||
|
|
||||||
// check if same instructions are used in another level
|
|
||||||
for (ri = ris; ri != null; ri = ri.next) {
|
|
||||||
if (size == 0) {
|
|
||||||
if (ri.list != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// both matchinglists are empty
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri.list == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ri.list.length != size)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (RenderInstruction r : ri.list) {
|
|
||||||
if (r != matches.get(i))
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i == size)
|
|
||||||
// both matching lists contain the same items
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri != null) {
|
|
||||||
// we found a same matchting list on another zoomlevel
|
|
||||||
ri.zoom |= zoomMask;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
ri = new RenderInstructionItem();
|
|
||||||
ri.zoom = zoomMask;
|
|
||||||
|
|
||||||
if (size > 0) {
|
|
||||||
ri.list = new RenderInstruction[size];
|
|
||||||
matches.toArray(ri.list);
|
|
||||||
}
|
|
||||||
// attach this list to the one found for MatchingKey
|
|
||||||
if (ris != null) {
|
|
||||||
ri.next = ris.next;
|
|
||||||
ri.key = ris.key;
|
|
||||||
ris.next = ri;
|
|
||||||
} else {
|
|
||||||
ri.key = new MatchingCacheKey(cacheKey);
|
|
||||||
mNodesCache.put(ri.key, ri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mPrevNodeItem = ri;
|
|
||||||
|
|
||||||
return ri.list;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches a way with the given parameters against this RenderTheme.
|
|
||||||
*
|
|
||||||
* @param tags
|
|
||||||
* the tags of the way.
|
|
||||||
* @param zoomLevel
|
|
||||||
* the zoom level at which the way should be matched.
|
|
||||||
* @param closed
|
|
||||||
* way is Closed
|
|
||||||
* @return currently processed render instructions
|
|
||||||
*/
|
|
||||||
public RenderInstruction[] matchWay(Tag[] tags, byte zoomLevel, boolean closed) {
|
|
||||||
|
|
||||||
// list of renderinsctruction items in cache
|
|
||||||
RenderInstructionItem ris = null;
|
|
||||||
|
|
||||||
RenderInstructionItem prevInstructions = null;
|
|
||||||
|
|
||||||
// the item matching tags and zoomlevel
|
|
||||||
RenderInstructionItem ri = null;
|
|
||||||
|
|
||||||
// temporary matching instructions list
|
|
||||||
List<RenderInstruction> matches;
|
|
||||||
|
|
||||||
LRUCache<MatchingCacheKey, RenderInstructionItem> matchingCache;
|
|
||||||
MatchingCacheKey cacheKey;
|
|
||||||
|
|
||||||
if (closed)
|
|
||||||
matchingCache = mAreaCache;
|
|
||||||
else
|
|
||||||
matchingCache = mWayCache;
|
|
||||||
|
|
||||||
int zoomMask = 1 << zoomLevel;
|
|
||||||
|
|
||||||
synchronized (matchingCache) {
|
|
||||||
if (closed) {
|
|
||||||
cacheKey = mAreaCacheKey;
|
|
||||||
matches = mAreaInstructionList;
|
|
||||||
prevInstructions = mPrevAreaItem;
|
|
||||||
} else {
|
|
||||||
cacheKey = mWayCacheKey;
|
|
||||||
matches = mWayInstructionList;
|
|
||||||
prevInstructions = mPrevWayItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevInstructions == null || (prevInstructions.zoom & zoomMask) == 0) {
|
|
||||||
// previous instructions zoom does not match
|
|
||||||
cacheKey.set(tags, null);
|
|
||||||
} else {
|
|
||||||
// compare if tags match previous instructions
|
|
||||||
if (cacheKey.set(tags, prevInstructions.key)) {
|
|
||||||
//Log.d(TAG, "same as previous " + Arrays.deepToString(tags));
|
//Log.d(TAG, "same as previous " + Arrays.deepToString(tags));
|
||||||
ri = prevInstructions;
|
ri = cache.prevItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ri == null) {
|
if (ri == null) {
|
||||||
ris = matchingCache.get(cacheKey);
|
ris = cache.cache.get(cache.cacheKey);
|
||||||
|
|
||||||
for (ri = ris; ri != null; ri = ri.next)
|
for (ri = ris; ri != null; ri = ri.next)
|
||||||
if ((ri.zoom & zoomMask) != 0)
|
if ((ri.zoom & zoomMask) != 0)
|
||||||
@ -337,12 +212,22 @@ public class RenderTheme {
|
|||||||
// cache miss
|
// cache miss
|
||||||
//Log.d(TAG, missCnt++ + " / " + hitCnt + " Cache Miss");
|
//Log.d(TAG, missCnt++ + " / " + hitCnt + " Cache Miss");
|
||||||
|
|
||||||
int c = (closed ? Closed.YES : Closed.NO);
|
List<RenderInstruction> matches = cache.instructionList;
|
||||||
//List<RenderInstruction> matches = mMatchingList;
|
|
||||||
matches.clear();
|
matches.clear();
|
||||||
|
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i)
|
if (type == GEOM_LINE) {
|
||||||
mRulesList.get(i).matchWay(tags, zoomLevel, c, matches);
|
for (int i = 0, n = mRules.length; i < n; i++)
|
||||||
|
mRules[i].matchWay(element.tags,
|
||||||
|
(byte) zoomLevel, Closed.NO, matches);
|
||||||
|
} else if (type == GEOM_POLY) {
|
||||||
|
for (int i = 0, n = mRules.length; i < n; i++)
|
||||||
|
mRules[i].matchWay(element.tags,
|
||||||
|
(byte) zoomLevel, Closed.YES, matches);
|
||||||
|
} else {
|
||||||
|
for (int i = 0, n = mRules.length; i < n; i++)
|
||||||
|
mRules[i].matchNode(element.tags,
|
||||||
|
(byte) zoomLevel, matches);
|
||||||
|
}
|
||||||
|
|
||||||
int size = matches.size();
|
int size = matches.size();
|
||||||
// check if same instructions are used in another level
|
// check if same instructions are used in another level
|
||||||
@ -373,12 +258,13 @@ public class RenderTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ri != null) {
|
if (ri != null) {
|
||||||
// we found a same matchting list on another zoomlevel
|
// we found a same matchting list on another zoomlevel add
|
||||||
|
// this zoom level to the existing RenderInstructionItem.
|
||||||
ri.zoom |= zoomMask;
|
ri.zoom |= zoomMask;
|
||||||
|
|
||||||
//Log.d(TAG,
|
//Log.d(TAG,
|
||||||
// zoomLevel + " same instructions " + size + " "
|
// zoomLevel + " same instructions " + size + " "
|
||||||
// + Arrays.deepToString(tags));
|
// + Arrays.deepToString(tags));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//Log.d(TAG,
|
//Log.d(TAG,
|
||||||
// zoomLevel + " new instructions " + size + " "
|
// zoomLevel + " new instructions " + size + " "
|
||||||
@ -398,56 +284,49 @@ public class RenderTheme {
|
|||||||
ri.key = ris.key;
|
ri.key = ris.key;
|
||||||
ris.next = ri;
|
ris.next = ri;
|
||||||
} else {
|
} else {
|
||||||
ri.key = new MatchingCacheKey(cacheKey);
|
ri.key = new MatchingCacheKey(cache.cacheKey);
|
||||||
matchingCache.put(ri.key, ri);
|
cache.cache.put(ri.key, ri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (closed)
|
|
||||||
mPrevAreaItem = ri;
|
cache.prevItem = ri;
|
||||||
else
|
|
||||||
mPrevWayItem = ri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ri.list;
|
return ri.list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRule(Rule rule) {
|
|
||||||
mRulesList.add(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
void complete() {
|
void complete(List<Rule> rulesList, int levels) {
|
||||||
mRulesList.trimToSize();
|
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
|
||||||
mRulesList.get(i).onComplete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLevels(int levels) {
|
|
||||||
mLevels = levels;
|
mLevels = levels;
|
||||||
|
|
||||||
|
mRules = new Rule[rulesList.size()];
|
||||||
|
rulesList.toArray(mRules);
|
||||||
|
|
||||||
|
for (int i = 0, n = mRules.length; i < n; i++) {
|
||||||
|
mRules[i].onComplete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Scales the stroke width of this RenderTheme by the given factor.
|
* (non-Javadoc)
|
||||||
*
|
* @see org.oscim.theme.IRenderTheme#scaleStrokeWidth(float)
|
||||||
* @param scaleFactor
|
|
||||||
* the factor by which the stroke width should be scaled.
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void scaleStrokeWidth(float scaleFactor) {
|
public void scaleStrokeWidth(float scaleFactor) {
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
|
||||||
mRulesList.get(i).scaleStrokeWidth(scaleFactor * mBaseStrokeWidth);
|
for (int i = 0, n = mRules.length; i < n; i++)
|
||||||
}
|
mRules[i].scaleStrokeWidth(scaleFactor * mBaseStrokeWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Scales the text size of this RenderTheme by the given factor.
|
* (non-Javadoc)
|
||||||
*
|
* @see org.oscim.theme.IRenderTheme#scaleTextSize(float)
|
||||||
* @param scaleFactor
|
|
||||||
* the factor by which the text size should be scaled.
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void scaleTextSize(float scaleFactor) {
|
public void scaleTextSize(float scaleFactor) {
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
|
||||||
mRulesList.get(i).scaleTextSize(scaleFactor * mBaseTextSize);
|
for (int i = 0, n = mRules.length; i < n; i++)
|
||||||
}
|
mRules[i].scaleTextSize(scaleFactor * mBaseTextSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ package org.oscim.theme;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if an I/O error occurs while reading from the input stream.
|
* if an I/O error occurs while reading from the input stream.
|
||||||
*/
|
*/
|
||||||
public static RenderTheme getRenderTheme(InputStream inputStream)
|
public static IRenderTheme getRenderTheme(InputStream inputStream)
|
||||||
throws SAXException,
|
throws SAXException,
|
||||||
ParserConfigurationException, IOException {
|
ParserConfigurationException, IOException {
|
||||||
RenderThemeHandler renderThemeHandler = new RenderThemeHandler();
|
RenderThemeHandler renderThemeHandler = new RenderThemeHandler();
|
||||||
@ -112,7 +113,9 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
Log.d(TAG, stringBuilder.toString());
|
Log.d(TAG, stringBuilder.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ArrayList<Rule> mRulesList = new ArrayList<Rule>();
|
||||||
private Rule mCurrentRule;
|
private Rule mCurrentRule;
|
||||||
|
|
||||||
private final Stack<Element> mElementStack = new Stack<Element>();
|
private final Stack<Element> mElementStack = new Stack<Element>();
|
||||||
private int mLevel;
|
private int mLevel;
|
||||||
private RenderTheme mRenderTheme;
|
private RenderTheme mRenderTheme;
|
||||||
@ -126,8 +129,8 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
throw new IllegalArgumentException("missing element: rules");
|
throw new IllegalArgumentException("missing element: rules");
|
||||||
}
|
}
|
||||||
|
|
||||||
mRenderTheme.setLevels(mLevel);
|
mRenderTheme.complete(mRulesList, mLevel);
|
||||||
mRenderTheme.complete();
|
mRulesList.clear();
|
||||||
tmpStyleHash.clear();
|
tmpStyleHash.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
if (ELEMENT_NAME_RULE.equals(localName)) {
|
if (ELEMENT_NAME_RULE.equals(localName)) {
|
||||||
mRuleStack.pop();
|
mRuleStack.pop();
|
||||||
if (mRuleStack.empty()) {
|
if (mRuleStack.empty()) {
|
||||||
mRenderTheme.addRule(mCurrentRule);
|
mRulesList.add(mCurrentRule);
|
||||||
} else {
|
} else {
|
||||||
mCurrentRule = mRuleStack.peek();
|
mCurrentRule = mRuleStack.peek();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user