performance refactoring
This commit is contained in:
parent
fe2c694ba6
commit
822f3c5fca
5 changed files with 105 additions and 81 deletions
|
@ -18,6 +18,9 @@
|
|||
from debug import debug, Timer
|
||||
from mapcss import MapCSS
|
||||
|
||||
import gc
|
||||
gc.disable()
|
||||
|
||||
import mapcss.webcolors
|
||||
whatever_to_hex = mapcss.webcolors.webcolors.whatever_to_hex
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ whatever_to_cairo = mapcss.webcolors.webcolors.whatever_to_cairo
|
|||
|
||||
WIDTH_SCALE = 1.0
|
||||
|
||||
|
||||
def komap_mapswithme(options, style):
|
||||
if options.outfile == "-":
|
||||
print "Please specify base output path."
|
||||
|
@ -58,8 +57,6 @@ def komap_mapswithme(options, style):
|
|||
if prefix:
|
||||
prefix += "-"
|
||||
opacity = hex(255 - int(255 * float(st.get(prefix + "opacity", 1))))
|
||||
if opacity == "0x0":
|
||||
opacity = "0x"
|
||||
color = whatever_to_hex(st.get(prefix + 'color', default))
|
||||
color = color[1] + color[1] + color[3] + color[3] + color[5] + color[5]
|
||||
return int(opacity + color, 16)
|
||||
|
@ -84,20 +81,20 @@ def komap_mapswithme(options, style):
|
|||
zstyle = {}
|
||||
|
||||
if "area" not in txclass:
|
||||
zstyle = style.get_style_dict("line", txclass, zoom, olddict=zstyle)
|
||||
zstyle = style.get_style_dict("line", txclass, zoom, olddict=zstyle, cache=False)
|
||||
# for st in zstyle:
|
||||
# if "fill-color" in st:
|
||||
# del st["fill-color"]
|
||||
|
||||
if True:
|
||||
areastyle = style.get_style_dict("area", txclass, zoom, olddict=zstyle)
|
||||
areastyle = style.get_style_dict("area", txclass, zoom, olddict=zstyle, cache=False)
|
||||
for st in areastyle.values():
|
||||
if "icon-image" in st or 'symbol-shape' in st:
|
||||
has_icons_for_areas = True
|
||||
zstyle = areastyle
|
||||
|
||||
if "area" not in txclass:
|
||||
nodestyle = style.get_style_dict("node", txclass, zoom, olddict=zstyle)
|
||||
nodestyle = style.get_style_dict("node", txclass, zoom, olddict=zstyle, cache=False)
|
||||
# for st in nodestyle:
|
||||
# if "fill-color" in st:
|
||||
# del st["fill-color"]
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with kothic. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
type_matches = {
|
||||
"": ('area', 'line', 'way', 'node'),
|
||||
"area": ("area", "way"),
|
||||
"node": ("node",),
|
||||
"way": ("line", "area", "way"),
|
||||
"line": ("line", "area"),
|
||||
}
|
||||
|
||||
class Rule():
|
||||
def __init__(self, s=''):
|
||||
|
@ -49,6 +56,9 @@ class Rule():
|
|||
def test_zoom(self, zoom):
|
||||
return (zoom >= self.minZoom) and (zoom <= self.maxZoom)
|
||||
|
||||
def get_compatible_types(self):
|
||||
return type_matches.get(self.subject, (self.subject,))
|
||||
|
||||
def get_interesting_tags(self, obj, zoom):
|
||||
if obj:
|
||||
if (self.subject != '') and not _test_feature_compatibility(obj, self.subject, {}):
|
||||
|
|
|
@ -22,22 +22,57 @@ from webcolors.webcolors import cairo_to_hex
|
|||
from Eval import Eval
|
||||
|
||||
|
||||
def make_nice_style(r):
|
||||
ra = {}
|
||||
for a, b in r.iteritems():
|
||||
"checking and nicifying style table"
|
||||
if type(b) == type(Eval()):
|
||||
ra[a] = b
|
||||
elif "color" in a:
|
||||
"parsing color value to 3-tuple"
|
||||
# print "res:", b
|
||||
if b and (type(b) != tuple):
|
||||
# if not b:
|
||||
# print sl, ftype, tags, zoom, scale, zscale
|
||||
# else:
|
||||
ra[a] = colorparser(b)
|
||||
elif b:
|
||||
ra[a] = b
|
||||
elif any(x in a for x in ("width", "z-index", "opacity", "offset", "radius", "extrude")):
|
||||
"these things are float's or not in table at all"
|
||||
try:
|
||||
ra[a] = float(b)
|
||||
except ValueError:
|
||||
pass
|
||||
elif "dashes" in a and type(b) != list:
|
||||
"these things are arrays of float's or not in table at all"
|
||||
try:
|
||||
b = b.split(",")
|
||||
b = [float(x) for x in b]
|
||||
ra[a] = b
|
||||
except ValueError:
|
||||
ra[a] = []
|
||||
else:
|
||||
ra[a] = b
|
||||
return ra
|
||||
|
||||
|
||||
class StyleChooser:
|
||||
"""
|
||||
A StyleChooser object is equivalent to one CSS selector+declaration.
|
||||
A StyleChooser object is equivalent to one CSS selector+declaration.
|
||||
|
||||
Its ruleChains property is an array of all the selectors, which would
|
||||
traditionally be comma-separated. For example:
|
||||
h1, h2, h3 em
|
||||
is three ruleChains.
|
||||
Its ruleChains property is an array of all the selectors, which would
|
||||
traditionally be comma-separated. For example:
|
||||
h1, h2, h3 em
|
||||
is three ruleChains.
|
||||
|
||||
Each ruleChain is itself an array of nested selectors. So the above
|
||||
example would roughly be encoded as:
|
||||
[[h1],[h2],[h3,em]]
|
||||
^^ ^^ ^^ ^^ each of these is a Rule
|
||||
Each ruleChain is itself an array of nested selectors. So the above
|
||||
example would roughly be encoded as:
|
||||
[[h1],[h2],[h3,em]]
|
||||
^^ ^^ ^^ ^^ each of these is a Rule
|
||||
|
||||
The styles property is an array of all the style objects to be drawn
|
||||
if any of the ruleChains evaluate to true.
|
||||
The styles property is an array of all the style objects to be drawn
|
||||
if any of the ruleChains evaluate to true.
|
||||
"""
|
||||
def __repr__(self):
|
||||
return "{(%s) : [%s] }\n" % (self.ruleChains, self.styles)
|
||||
|
@ -48,6 +83,8 @@ class StyleChooser:
|
|||
self.eval_type = type(Eval())
|
||||
self.scalepair = scalepair
|
||||
self.selzooms = None
|
||||
self.compatible_types = set()
|
||||
self.has_evals = False
|
||||
|
||||
def get_numerics(self):
|
||||
"""
|
||||
|
@ -103,6 +140,9 @@ class StyleChooser:
|
|||
if zoom < self.selzooms[0] or zoom > self.selzooms[1]:
|
||||
return sl
|
||||
|
||||
#if ftype not in self.compatible_types:
|
||||
# return sl
|
||||
|
||||
object_id = self.testChain(self.ruleChains, ftype, tags, zoom)
|
||||
|
||||
if not object_id:
|
||||
|
@ -111,50 +151,24 @@ class StyleChooser:
|
|||
w = 0
|
||||
|
||||
for r in self.styles:
|
||||
ra = {}
|
||||
for a, b in r.iteritems():
|
||||
"calculating eval()'s"
|
||||
if type(b) == self.eval_type:
|
||||
combined_style = {}
|
||||
for t in sl:
|
||||
combined_style.update(t)
|
||||
for p, q in combined_style.iteritems():
|
||||
if "color" in p:
|
||||
combined_style[p] = cairo_to_hex(q)
|
||||
b = b.compute(tags, combined_style, scale, zscale)
|
||||
ra[a] = b
|
||||
r = ra
|
||||
ra = {}
|
||||
|
||||
for a, b in r.iteritems():
|
||||
"checking and nicifying style table"
|
||||
if "color" in a:
|
||||
"parsing color value to 3-tuple"
|
||||
# print "res:", b
|
||||
if b:
|
||||
# if not b:
|
||||
# print sl, ftype, tags, zoom, scale, zscale
|
||||
# else:
|
||||
ra[a] = colorparser(b)
|
||||
elif any(x in a for x in ("width", "z-index", "opacity", "offset", "radius", "extrude")):
|
||||
"these things are float's or not in table at all"
|
||||
try:
|
||||
ra[a] = float(b)
|
||||
except ValueError:
|
||||
pass
|
||||
elif "dashes" in a:
|
||||
"these things are arrays of float's or not in table at all"
|
||||
try:
|
||||
b = b.split(",")
|
||||
b = [float(x) for x in b]
|
||||
ra[a] = b
|
||||
except ValueError:
|
||||
ra[a] = []
|
||||
else:
|
||||
if self.has_evals:
|
||||
ra = {}
|
||||
for a, b in r.iteritems():
|
||||
"calculating eval()'s"
|
||||
if type(b) == self.eval_type:
|
||||
combined_style = {}
|
||||
for t in sl:
|
||||
combined_style.update(t)
|
||||
for p, q in combined_style.iteritems():
|
||||
if "color" in p:
|
||||
combined_style[p] = cairo_to_hex(q)
|
||||
b = b.compute(tags, combined_style, scale, zscale)
|
||||
ra[a] = b
|
||||
# for k,v in ra.items(): # if a value is empty, we don't need it - renderer will do as default.
|
||||
# if not v:
|
||||
# del ra[k]
|
||||
#r = ra
|
||||
ra = make_nice_style(ra)
|
||||
else:
|
||||
ra = r.copy()
|
||||
|
||||
ra["object-id"] = str(object_id)
|
||||
hasall = False
|
||||
allinit = {}
|
||||
|
@ -224,6 +238,7 @@ class StyleChooser:
|
|||
else:
|
||||
self.selzooms[0] = min(self.selzooms[0], r.minZoom)
|
||||
self.selzooms[1] = max(self.selzooms[1], r.maxZoom)
|
||||
self.compatible_types.update(r.get_compatible_types())
|
||||
rb = []
|
||||
for r in a:
|
||||
ra = {}
|
||||
|
@ -242,6 +257,8 @@ class StyleChooser:
|
|||
b = "eval(tag(\"" + b + "\"))"
|
||||
if b[:5] == "eval(":
|
||||
b = Eval(b)
|
||||
self.has_evals = True
|
||||
ra[a] = b
|
||||
ra = make_nice_style(ra)
|
||||
rb.append(ra)
|
||||
self.styles = self.styles + rb
|
||||
|
|
|
@ -85,15 +85,6 @@ CENTER = re.compile(r'^center$/i')
|
|||
|
||||
HEX = re.compile(r'^#([0-9a-f]+)$/i')
|
||||
|
||||
|
||||
builtin_style = """
|
||||
canvas {fill-color: #cccccc}
|
||||
way {width: 1; casing-width:1; casing-color: white}
|
||||
"""
|
||||
|
||||
|
||||
## ** also needs to support @import rules
|
||||
|
||||
class MapCSS():
|
||||
def __init__(self, minscale=0, maxscale=19):
|
||||
"""
|
||||
|
@ -104,9 +95,8 @@ class MapCSS():
|
|||
self.maxscale = maxscale
|
||||
self.scalepair = (minscale, maxscale)
|
||||
self.choosers = []
|
||||
self.choosers_by_type = {}
|
||||
self.style_loaded = False
|
||||
self.parse(builtin_style)
|
||||
self.style_loaded = False # override one after loading
|
||||
|
||||
def parseZoom(self, s):
|
||||
if ZOOM_MINMAX.match(s):
|
||||
|
@ -120,15 +110,16 @@ class MapCSS():
|
|||
else:
|
||||
logging.error("unparsed zoom: %s" % s)
|
||||
|
||||
def get_style(self, type, tags={}, zoom=0, scale=1, zscale=.5):
|
||||
def get_style(self, type, tags={}, zoom=0, scale=1, zscale=.5, cache=True):
|
||||
"""
|
||||
Kothic styling API
|
||||
"""
|
||||
shash = md5(repr(type) + repr(tags) + repr(zoom)).digest()
|
||||
if shash in self.cache["style"]:
|
||||
return deepcopy(self.cache["style"][shash])
|
||||
if cache:
|
||||
shash = md5(repr(type) + repr(tags) + repr(zoom)).digest()
|
||||
if shash in self.cache["style"]:
|
||||
return deepcopy(self.cache["style"][shash])
|
||||
style = []
|
||||
for chooser in self.choosers:
|
||||
for chooser in self.choosers_by_type[type]:
|
||||
style = chooser.updateStyles(style, type, tags, zoom, scale, zscale)
|
||||
style = [x for x in style if x["object-id"] != "::*"]
|
||||
st = []
|
||||
|
@ -143,11 +134,12 @@ class MapCSS():
|
|||
st.append(x)
|
||||
style = st
|
||||
|
||||
self.cache["style"][shash] = style
|
||||
return deepcopy(style)
|
||||
if cache:
|
||||
self.cache["style"][shash] = deepcopy(style)
|
||||
return style
|
||||
|
||||
def get_style_dict(self, type, tags={}, zoom=0, scale=1, zscale=.5, olddict={}):
|
||||
r = self.get_style(type, tags, zoom, scale, zscale)
|
||||
def get_style_dict(self, type, tags={}, zoom=0, scale=1, zscale=.5, olddict={}, cache=True):
|
||||
r = self.get_style(type, tags, zoom, scale, zscale, cache)
|
||||
d = olddict
|
||||
for x in r:
|
||||
if x.get('object-id', '') not in d:
|
||||
|
@ -315,6 +307,12 @@ class MapCSS():
|
|||
|
||||
except TypeError:
|
||||
pass
|
||||
for chooser in self.choosers:
|
||||
for t in chooser.compatible_types:
|
||||
if t not in self.choosers_by_type:
|
||||
self.choosers_by_type[t] = [chooser]
|
||||
else:
|
||||
self.choosers_by_type[t].append(chooser)
|
||||
|
||||
|
||||
def parseCondition(s):
|
||||
|
@ -347,7 +345,6 @@ def parseCondition(s):
|
|||
a = CONDITION_NE.match(s).groups()
|
||||
log.debug("condition NE: %s = %s" % (a[0], a[1]))
|
||||
return Condition('ne', a)
|
||||
## FIXME: convert other conditions to python
|
||||
|
||||
if CONDITION_LE.match(s):
|
||||
a = CONDITION_LE.match(s).groups()
|
||||
|
|
Loading…
Add table
Reference in a new issue