diff --git a/src/libkomwm.py b/src/libkomwm.py index 2270aef..9e18094 100644 --- a/src/libkomwm.py +++ b/src/libkomwm.py @@ -5,14 +5,15 @@ from optparse import OptionParser import os import csv import sys -import json import mapcss.webcolors whatever_to_hex = mapcss.webcolors.webcolors.whatever_to_hex whatever_to_cairo = mapcss.webcolors.webcolors.whatever_to_cairo + WIDTH_SCALE = 1.0 -def komap_mapswithme(options, style, filename): + +def komap_mapswithme(options, style): if options.outfile == "-": print "Please specify base output path." exit() @@ -23,7 +24,6 @@ def komap_mapswithme(options, style, filename): drules_bin = open(os.path.join(options.outfile + '.bin'), "wb") drules_txt = open(os.path.join(options.outfile + '.txt'), "wb") - drules = ContainerProto() classificator = {} class_order = [] class_tree = {} @@ -96,12 +96,14 @@ def komap_mapswithme(options, style, filename): style.build_choosers_tree(clname, "area", classificator[cl]) style.build_choosers_tree(clname, "node", classificator[cl]) - style.restore_choosers_order("line"); - style.restore_choosers_order("area"); - style.restore_choosers_order("node"); + style.restore_choosers_order("line") + style.restore_choosers_order("area") + style.restore_choosers_order("node") # atbuild.Stop() + drules = ContainerProto() + for cl in class_order: visstring = ["0"] * (options.maxzoom - options.minzoom + 1) @@ -133,7 +135,7 @@ def komap_mapswithme(options, style, filename): if check_line: if "area" not in txclass: # atline.Start() - linestyle = style.get_style_dict(clname, "line", txclass, zoom, olddict=zstyle, cache=False) + linestyle = style.get_style_dict(clname, "line", txclass, zoom, olddict=zstyle) if prev_line_len == -1: prev_line_len = len(linestyle) if len(linestyle) == 0: @@ -144,7 +146,7 @@ def komap_mapswithme(options, style, filename): if check_area: # atarea.Start() - areastyle = style.get_style_dict(clname, "area", txclass, zoom, olddict=zstyle, cache=False) + areastyle = style.get_style_dict(clname, "area", txclass, zoom, olddict=zstyle) for st in areastyle.values(): if "icon-image" in st or 'symbol-shape' in st or 'symbol-image' in st: has_icons_for_areas = True @@ -160,7 +162,7 @@ def komap_mapswithme(options, style, filename): if check_node: if "area" not in txclass: # atnode.Start() - nodestyle = style.get_style_dict(clname, "node", txclass, zoom, olddict=zstyle, cache=False) + nodestyle = style.get_style_dict(clname, "node", txclass, zoom, olddict=zstyle) if prev_node_len == -1: prev_node_len = len(nodestyle) if len(nodestyle) == 0: @@ -183,10 +185,12 @@ def komap_mapswithme(options, style, filename): dr_cont = ClassifElementProto() dr_cont.name = cl + for zoom in xrange(options.minzoom, options.maxzoom + 1): zstyle = zstyles_arr[zoom - options.minzoom] if zstyle is None or len(zstyle) == 0: continue + has_icons_for_areas = has_icons_for_areas_arr[zoom - options.minzoom] has_lines = False @@ -210,129 +214,131 @@ def komap_mapswithme(options, style, filename): has_text = [] has_text.append(st) - if has_lines or has_text or has_fills or has_icons: - visstring[zoom] = "1" - dr_element = DrawElementProto() - dr_element.scale = zoom + if (not has_lines) and (not has_text) and (not has_fills) and (not has_icons): + continue - for st in zstyle: - if st.get('-x-kot-layer') == 'top': - st['z-index'] = float(st.get('z-index', 0)) + 15001. - elif st.get('-x-kot-layer') == 'bottom': - st['z-index'] = float(st.get('z-index', 0)) - 15001. + visstring[zoom] = "1" + dr_element = DrawElementProto() + dr_element.scale = zoom - if st.get('casing-width') not in (None, 0): # and (st.get('width') or st.get('fill-color')): - if st.get('casing-linecap', 'butt') == 'butt': - dr_line = LineRuleProto() - dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2) - dr_line.color = mwm_encode_color(st, "casing") - dr_line.priority = min(int(st.get('z-index', 0) + 999), 20000) - dashes = st.get('casing-dashes', st.get('dashes', [])) - dr_line.dashdot.dd.extend(dashes) - dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'butt'), BUTTCAP) - dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN) - dr_element.lines.extend([dr_line]) + for st in zstyle: + if st.get('-x-kot-layer') == 'top': + st['z-index'] = float(st.get('z-index', 0)) + 15001. + elif st.get('-x-kot-layer') == 'bottom': + st['z-index'] = float(st.get('z-index', 0)) - 15001. - # Let's try without this additional line style overhead. Needed only for casing in road endings. - # if st.get('casing-linecap', st.get('linecap', 'round')) != 'butt': - # dr_line = LineRuleProto() - # dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2) - # dr_line.color = mwm_encode_color(st, "casing") - # dr_line.priority = -15000 - # dashes = st.get('casing-dashes', st.get('dashes', [])) - # dr_line.dashdot.dd.extend(dashes) - # dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'round'), ROUNDCAP) - # dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN) - # dr_element.lines.extend([dr_line]) + if st.get('casing-width') not in (None, 0): # and (st.get('width') or st.get('fill-color')): + if st.get('casing-linecap', 'butt') == 'butt': + dr_line = LineRuleProto() + dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2) + dr_line.color = mwm_encode_color(st, "casing") + dr_line.priority = min(int(st.get('z-index', 0) + 999), 20000) + dashes = st.get('casing-dashes', st.get('dashes', [])) + dr_line.dashdot.dd.extend(dashes) + dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'butt'), BUTTCAP) + dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN) + dr_element.lines.extend([dr_line]) - if has_lines: - if st.get('width'): - dr_line = LineRuleProto() - dr_line.width = (st.get('width', 0) * WIDTH_SCALE) - dr_line.color = mwm_encode_color(st) - for i in st.get('dashes', []): - dr_line.dashdot.dd.extend([max(float(i), 1) * WIDTH_SCALE]) - dr_line.cap = dr_linecaps.get(st.get('linecap', 'butt'), BUTTCAP) - dr_line.join = dr_linejoins.get(st.get('linejoin', 'round'), ROUNDJOIN) - dr_line.priority = min((int(st.get('z-index', 0)) + 1000), 20000) - dr_element.lines.extend([dr_line]) - if st.get('pattern-image'): - dr_line = LineRuleProto() - dr_line.width = 0 - dr_line.color = 0 - icon = mwm_encode_image(st, prefix='pattern') - dr_line.pathsym.name = icon[0] - dr_line.pathsym.step = float(st.get('pattern-spacing', 0)) - 16 - dr_line.pathsym.offset = st.get('pattern-offset', 0) - dr_line.priority = int(st.get('z-index', 0)) + 1000 - dr_element.lines.extend([dr_line]) - textures[icon[0]] = icon[1] - if st.get('shield-font-size'): - dr_element.shield.height = int(st.get('shield-font-size', 10)) - dr_element.shield.color = mwm_encode_color(st, "shield-text") - if st.get('shield-text-halo-radius', 0) != 0: - dr_element.shield.stroke_color = mwm_encode_color(st, "shield-text-halo", "white") - dr_element.shield.priority = min(19100, (16000 + int(st.get('z-index', 0)))) + # Let's try without this additional line style overhead. Needed only for casing in road endings. + # if st.get('casing-linecap', st.get('linecap', 'round')) != 'butt': + # dr_line = LineRuleProto() + # dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2) + # dr_line.color = mwm_encode_color(st, "casing") + # dr_line.priority = -15000 + # dashes = st.get('casing-dashes', st.get('dashes', [])) + # dr_line.dashdot.dd.extend(dashes) + # dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'round'), ROUNDCAP) + # dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN) + # dr_element.lines.extend([dr_line]) - if has_icons: - if st.get('icon-image'): - if not has_icons_for_areas: - dr_element.symbol.apply_for_type = 1 - icon = mwm_encode_image(st) - dr_element.symbol.name = icon[0] - dr_element.symbol.priority = min(19100, (16000 + int(st.get('z-index', 0)))) - textures[icon[0]] = icon[1] - has_icons = False - if st.get('symbol-shape'): - dr_element.circle.radius = float(st.get('symbol-size')) - dr_element.circle.color = mwm_encode_color(st, 'symbol-fill') - dr_element.circle.priority = min(19000, (14000 + int(st.get('z-index', 0)))) - has_icons = False + if has_lines: + if st.get('width'): + dr_line = LineRuleProto() + dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + dr_line.color = mwm_encode_color(st) + for i in st.get('dashes', []): + dr_line.dashdot.dd.extend([max(float(i), 1) * WIDTH_SCALE]) + dr_line.cap = dr_linecaps.get(st.get('linecap', 'butt'), BUTTCAP) + dr_line.join = dr_linejoins.get(st.get('linejoin', 'round'), ROUNDJOIN) + dr_line.priority = min((int(st.get('z-index', 0)) + 1000), 20000) + dr_element.lines.extend([dr_line]) + if st.get('pattern-image'): + dr_line = LineRuleProto() + dr_line.width = 0 + dr_line.color = 0 + icon = mwm_encode_image(st, prefix='pattern') + dr_line.pathsym.name = icon[0] + dr_line.pathsym.step = float(st.get('pattern-spacing', 0)) - 16 + dr_line.pathsym.offset = st.get('pattern-offset', 0) + dr_line.priority = int(st.get('z-index', 0)) + 1000 + dr_element.lines.extend([dr_line]) + textures[icon[0]] = icon[1] + if st.get('shield-font-size'): + dr_element.shield.height = int(st.get('shield-font-size', 10)) + dr_element.shield.color = mwm_encode_color(st, "shield-text") + if st.get('shield-text-halo-radius', 0) != 0: + dr_element.shield.stroke_color = mwm_encode_color(st, "shield-text-halo", "white") + dr_element.shield.priority = min(19100, (16000 + int(st.get('z-index', 0)))) - if has_text and st.get('text'): - has_text = has_text[:2] - has_text.reverse() + if has_icons: + if st.get('icon-image'): + if not has_icons_for_areas: + dr_element.symbol.apply_for_type = 1 + icon = mwm_encode_image(st) + dr_element.symbol.name = icon[0] + dr_element.symbol.priority = min(19100, (16000 + int(st.get('z-index', 0)))) + textures[icon[0]] = icon[1] + has_icons = False + if st.get('symbol-shape'): + dr_element.circle.radius = float(st.get('symbol-size')) + dr_element.circle.color = mwm_encode_color(st, 'symbol-fill') + dr_element.circle.priority = min(19000, (14000 + int(st.get('z-index', 0)))) + has_icons = False + + if has_text and st.get('text'): + has_text = has_text[:2] + has_text.reverse() + dr_text = dr_element.path_text + base_z = 15000 + if st.get('text-position', 'center') == 'line': dr_text = dr_element.path_text - base_z = 15000 - if st.get('text-position', 'center') == 'line': - dr_text = dr_element.path_text - base_z = 16000 - else: - dr_text = dr_element.caption - for sp in has_text[:]: - dr_cur_subtext = dr_text.primary - if len(has_text) == 2: - dr_cur_subtext = dr_text.secondary - dr_cur_subtext.height = int(float(sp.get('font-size', "10").split(",")[0])) - dr_cur_subtext.color = mwm_encode_color(sp, "text") - if st.get('text-halo-radius', 0) != 0: - dr_cur_subtext.stroke_color = mwm_encode_color(sp, "text-halo", "white") - if 'text-offset' in sp or 'text-offset-y' in sp: - dr_cur_subtext.offset_y = int(sp.get('text-offset-y', sp.get('text-offset', 0))) - if 'text-offset-x' in sp: - dr_cur_subtext.offset_x = int(sp.get('text-offset-x', 0)) - has_text.pop() - dr_text.priority = min(19000, (base_z + int(st.get('z-index', 0)))) - has_text = None + base_z = 16000 + else: + dr_text = dr_element.caption + for sp in has_text[:]: + dr_cur_subtext = dr_text.primary + if len(has_text) == 2: + dr_cur_subtext = dr_text.secondary + dr_cur_subtext.height = int(float(sp.get('font-size', "10").split(",")[0])) + dr_cur_subtext.color = mwm_encode_color(sp, "text") + if st.get('text-halo-radius', 0) != 0: + dr_cur_subtext.stroke_color = mwm_encode_color(sp, "text-halo", "white") + if 'text-offset' in sp or 'text-offset-y' in sp: + dr_cur_subtext.offset_y = int(sp.get('text-offset-y', sp.get('text-offset', 0))) + if 'text-offset-x' in sp: + dr_cur_subtext.offset_x = int(sp.get('text-offset-x', 0)) + has_text.pop() + dr_text.priority = min(19000, (base_z + int(st.get('z-index', 0)))) + has_text = None - if has_fills: - if ('fill-color' in st) and (float(st.get('fill-opacity', 1)) > 0): - dr_element.area.color = mwm_encode_color(st, "fill") - if st.get('fill-position', 'foreground') == 'background': - if 'z-index' not in st: - bgpos -= 1 - dr_element.area.priority = bgpos - 16000 - else: - zzz = int(st.get('z-index', 0)) - if zzz > 0: - dr_element.area.priority = zzz - 16000 - else: - dr_element.area.priority = zzz - 16700 + if has_fills: + if ('fill-color' in st) and (float(st.get('fill-opacity', 1)) > 0): + dr_element.area.color = mwm_encode_color(st, "fill") + if st.get('fill-position', 'foreground') == 'background': + if 'z-index' not in st: + bgpos -= 1 + dr_element.area.priority = bgpos - 16000 else: - dr_element.area.priority = (int(st.get('z-index', 0)) + 1 + 1000) - has_fills = False + zzz = int(st.get('z-index', 0)) + if zzz > 0: + dr_element.area.priority = zzz - 16000 + else: + dr_element.area.priority = zzz - 16700 + else: + dr_element.area.priority = (int(st.get('z-index', 0)) + 1 + 1000) + has_fills = False - dr_cont.element.extend([dr_element]) + dr_cont.element.extend([dr_element]) if dr_cont.element: drules.cont.extend([dr_cont]) @@ -403,18 +409,8 @@ parser.add_option("-f", "--minzoom", dest="minzoom", default=0, type="int", help="minimal available zoom level", metavar="ZOOM") parser.add_option("-t", "--maxzoom", dest="maxzoom", default=19, type="int", help="maximal available zoom level", metavar="ZOOM") -parser.add_option("-l", "--locale", dest="locale", - help="language that should be used for labels (ru, en, be, uk..)", metavar="LANG") parser.add_option("-o", "--output-file", dest="outfile", default="-", help="output filename (defaults to stdout)", metavar="FILE") -parser.add_option("-p", "--osm2pgsql-style", dest="osm2pgsqlstyle", default="-", - help="osm2pgsql stylesheet filename", metavar="FILE") -parser.add_option("-b", "--background-only", dest="bgonly", action="store_true", default=False, - help="Skip rendering of icons and labels", metavar="BOOL") -parser.add_option("-T", "--text-scale", dest="textscale", default=1, type="float", - help="text size scale", metavar="SCALE") -parser.add_option("-c", "--config", dest="conffile", default="komap.conf", - help="config file name", metavar="FILE") (options, args) = parser.parse_args() @@ -431,7 +427,7 @@ try: # atparse.Stop() # atbuild.Start() - komap_mapswithme(options, style, options.filename) + komap_mapswithme(options, style) # atbuild.Stop() # print "mapcss parse, sec: %s" % (atparse.ElapsedSec()) diff --git a/src/mapcss/Condition.py b/src/mapcss/Condition.py index 768919d..1715643 100644 --- a/src/mapcss/Condition.py +++ b/src/mapcss/Condition.py @@ -101,7 +101,6 @@ class Condition: self.params = params # e.g. ('highway','primary') if typez == "regex": self.regex = re.compile(self.params[0], re.I) - self.compiled_regex = "" def extract_tags(self): if self.params[0][:2] == "::" or self.type == "regex": @@ -136,7 +135,6 @@ class Condition: if params[0] in tags: return tags[params[0]] == '' return True - if t == '<': return (Number(tags[params[0]]) < Number(params[1])) if t == '<=': diff --git a/src/mapcss/StyleChooser.py b/src/mapcss/StyleChooser.py index 77e8d6c..1cfd2b6 100644 --- a/src/mapcss/StyleChooser.py +++ b/src/mapcss/StyleChooser.py @@ -113,15 +113,13 @@ class StyleChooser: return sl #if ftype not in self.compatible_types: -# return sl + #return sl object_id = self.testChain(self.ruleChains, ftype, tags, zoom) if not object_id: return sl - w = 0 - for r in self.styles: if self.has_evals: ra = {} @@ -136,7 +134,6 @@ class StyleChooser: combined_style[p] = cairo_to_hex(q) b = b.compute(tags, combined_style, scale, zscale) ra[a] = b - #r = ra ra = make_nice_style(ra) else: ra = r.copy() diff --git a/src/mapcss/__init__.py b/src/mapcss/__init__.py index 9efbff8..9e87b1c 100644 --- a/src/mapcss/__init__.py +++ b/src/mapcss/__init__.py @@ -18,11 +18,6 @@ import re import os import logging -from hashlib import md5 - -from copy import copy, deepcopy - - from StyleChooser import StyleChooser from Condition import Condition @@ -30,7 +25,6 @@ from Condition import Condition NEEDED_KEYS = set(["width", "casing-width", "fill-color", "fill-image", "icon-image", "text", "extrude", "background-image", "background-color", "pattern-image", "shield-text", "symbol-shape"]) - WHITESPACE = re.compile(r'^ \s+ ', re.S | re.X) COMMENT = re.compile(r'^ \/\* .+? \*\/ \s* ', re.S | re.X) @@ -139,14 +133,10 @@ class MapCSS(): tmp.append(ec) self.choosers_by_type_and_tag[type][tag] = tmp - def get_style(self, clname, type, tags={}, zoom=0, scale=1, zscale=.5, cache=True): + def get_style(self, clname, type, tags={}, zoom=0, scale=1, zscale=.5): """ Kothic styling API """ - if cache: - shash = md5(repr(type) + repr(tags) + repr(zoom)).digest() - if shash in self.cache["style"]: - return deepcopy(self.cache["style"][shash]) style = [] if type in self.choosers_by_type_and_tag: choosers = self.choosers_by_type_and_tag[type][clname] @@ -163,13 +153,10 @@ class MapCSS(): if not NEEDED_KEYS.isdisjoint(x): st.append(x) style = st - - if cache: - self.cache["style"][shash] = deepcopy(style) return style - def get_style_dict(self, clname, type, tags={}, zoom=0, scale=1, zscale=.5, olddict={}, cache=True): - r = self.get_style(clname, type, tags, zoom, scale, zscale, cache) + def get_style_dict(self, clname, type, tags={}, zoom=0, scale=1, zscale=.5, olddict={}): + r = self.get_style(clname, type, tags, zoom, scale, zscale) d = olddict for x in r: if x.get('object-id', '') not in d: