Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Rewrite mapcss files from pseudo-tags to OM types #31

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions src/libkomwm.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ def komap_mapswithme(options):
ddir = os.path.dirname(options.outfile)

classificator = {}
tags_to_cl = {}
class_order = []
class_tree = {}

Expand Down Expand Up @@ -514,17 +515,26 @@ def addPattern(dashes):
raise Exception('Duplicate type: {0}'.format(row[0]))
pairs = [i.strip(']').split("=") for i in row[1].split(',')[0].split('[')]
kv = OrderedDict()
match_tags = ''
for i in pairs:
if len(i) == 1:
if i[0]:
if i[0][0] == "!":
kv[i[0][1:].strip('?')] = "no"
# Skip match_tags.
else:
kv[i[0].strip('?')] = "yes"
match_tags += '[' + i[0] + ']'
else:
kv[i[0]] = i[1]
match_tags += '[' + i[0] + '=' + i[1] + ']'
if row[2] != "x":
classificator[cl] = kv
if match_tags not in tags_to_cl:
tags_to_cl[match_tags] = cl
else:
print(f'WARNING: not unique match_tags: {match_tags}={cl}, previous ={tags_to_cl[match_tags]}')
#tags_to_cl[row[1].split(',')[0]] = cl
class_order.append(cl)
unique_types_check.add(cl)
# Mark original type to distinguish it among replacing types.
Expand All @@ -539,6 +549,28 @@ def addPattern(dashes):
class_order.sort()
types_file.close()

#pastk
#cl = 'leisure-track-area'
#print(cl, classificator[cl]) #OrderedDict([('leisure', 'track'), ('area', 'yes')])
#tags = '[leisure=track][area?]'
#print(tags, tags_to_cl[tags])
#tags = '[railway=rail][highspeed?]' #'[railway=rail][highspeed?][!service]'
#print(tags, tags_to_cl[tags])

# Manually-assisted conversions:
tags_to_cl['[place]'] = 'place'
tags_to_cl['[leisure]'] = 'leisure'
tags_to_cl['[waterway]'] = 'waterway'
tags_to_cl['[isoline]'] = 'isoline'
tags_to_cl['[sport]'] = 'sport'
tags_to_cl['[tourism]'] = 'tourism'
tags_to_cl['[craft]'] = 'craft'
tags_to_cl['[shop]'] = 'shop'
tags_to_cl['[highway]'] = 'highway'
tags_to_cl['[landuse=military][military=danger_area]'] = 'landuse-military-danger_area'
tags_to_cl['[railway=rail][bridge?]'] = 'railway-rail-bridge'
tags_to_cl['[railway=rail][tunnel?]'] = 'railway-rail-tunnel'

output = ''
for prio_range in prio_ranges.keys():
load_priorities(prio_range, options.priorities_path, unique_types_check, compress = False)
Expand All @@ -560,9 +592,8 @@ def addPattern(dashes):
# Parse style mapcss
global style
style = MapCSS(options.minzoom, options.maxzoom)
style.parse(clamp=False, stretch=LAYER_PRIORITY_RANGE,
filename=options.filename, static_tags=mapcss_static_tags,
dynamic_tags=mapcss_dynamic_tags)
style.parse(filename=options.filename, static_tags=mapcss_static_tags,
dynamic_tags=mapcss_dynamic_tags, rewrite = True, tags_to_cl = tags_to_cl)

# Build optimization tree - class/zoom/type -> StyleChoosers
clname_cltag_unique = set()
Expand Down
121 changes: 78 additions & 43 deletions src/mapcss/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
#NOT_CLASS = re.compile(r'!([\.:]\w+) \s* ', re.S | re.X)
ZOOM = re.compile(r'\| \s* z([\d\-]+) \s* ', re.I | re.S | re.X)
GROUP = re.compile(r', \s* ', re.I | re.S | re.X)
CONDITION = re.compile(r'\[(.+?)\] \s* ', re.S | re.X)
OBJECT = re.compile(r'(\*|[\w]+) \s* ', re.S | re.X)
CONDITION = re.compile(r'\[(.+?)\] (\s*) ', re.S | re.X)
OBJECT = re.compile(r'(\*|[\w]+) (\s*) ', re.S | re.X)
DECLARATION = re.compile(r'\{(.*?)\} \s* ', re.S | re.X)
IMPORT = re.compile(r'@import\("(.+?)"\); \s* ', re.S | re.X)
VARIABLE_SET = re.compile(r'@([a-z][\w\d]*) \s* : \s* (.+?) \s* ; \s* ', re.S | re.X | re.I)
Expand Down Expand Up @@ -211,7 +211,7 @@ def get_variable(self, m):
raise Exception("Variable not found: " + str(format(name)))
return self.variables[name] if name in self.variables else m.group()

def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={}, dynamic_tags=set()):
def parse(self, css=None, filename=None, static_tags={}, dynamic_tags=set(), rewrite = False, tags_to_cl = {}):
"""
Parses MapCSS given as string
"""
Expand All @@ -226,9 +226,24 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={
log = logging.getLogger('mapcss.parser')
previous = oNONE # what was the previous CSS word?
sc = StyleChooser(self.scalepair) # currently being assembled
full_condition = ''

stck = [] # filename, original, remained
stck = [] # filename, remained, original
stck.append([filename, css, css])
if rewrite:
out_file = open(stck[-1][0], 'w')

def rewrite_file(s):
if rewrite:
out_file.write(s)

def convert_to_cl(tags):
if tags in tags_to_cl:
#return tags # DEBUG To focus on non-matches only.
return '|' + tags_to_cl[tags]
# There is no OM type for this combination of tags. Have to migrate manually.
return '|' + tags + ' /*NO-TYPE-MATCH*/'

try:
while (len(stck) > 0):
css = stck[-1][1].lstrip() # remained
Expand All @@ -240,35 +255,35 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={
if previous == oDECLARATION:
self.choosers.append(sc)
sc = StyleChooser(self.scalepair)
cond = CLASS.match(css).groups()[0]
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
m = CLASS.match(css)
rewrite_file(m.group(0))
cond = m.group(1)
log.debug("class found: %s" % (cond))
css = CLASS.sub("", css, 1)
sc.addCondition(Condition('eq', ("::class", cond)))
previous = oCONDITION

## Not class - !.motorway, !.builtup, !:hover
#elif NOT_CLASS.match(css):
#if (previous == oDECLARATION):
#self.choosers.append(sc)
#sc = StyleChooser(self.scalepair)
#cond = NOT_CLASS.match(css).groups()[0]
#log.debug("not_class found: %s" % (cond))
#css = NOT_CLASS.sub("", css, 1)
#sc.addCondition(Condition('ne', ("::class", cond)))
#previous = oCONDITION

# Zoom
elif ZOOM.match(css):
if (previous != oOBJECT & previous != oCONDITION):
sc.newObject()
cond = ZOOM.match(css).groups()[0]
m = ZOOM.match(css)
rewrite_file(m.group(0))
cond = m.group(1)
log.debug("zoom found: %s" % (cond))
css = ZOOM.sub("", css, 1)
sc.addZoom(self.parseZoom(cond))
previous = oZOOM

# Grouping - just a comma
elif GROUP.match(css):
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
rewrite_file(GROUP.match(css).group(0))
css = GROUP.sub("", css, 1)
sc.newGroup()
had_main_tag = False
Expand All @@ -283,23 +298,36 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={
if (previous != oOBJECT) and (previous != oZOOM) and (previous != oCONDITION):
sc.newObject()
had_main_tag = False
cond = CONDITION.match(css).groups()[0]
m = CONDITION.match(css)
cond = m.group(1)
c = parseCondition(cond)
tag = c.extract_tag()
tag_type = static_tags.get(tag, None)
if tag == "*" or tag_type is not None:
if tag_type and had_main_tag:
if rewrite:
if full_condition:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
rewrite_file('[' + cond + ']' + m.group(2))
if '!' in cond:
condType = 'ne'
cond = cond.replace('!', '')
else:
condType = 'eq'
sc.addRuntimeCondition(Condition(condType, ('extra_tag', cond)))
else:
if rewrite:
full_condition += '[' + cond + ']'
sc.addCondition(c)
if tag_type:
had_main_tag = True
elif tag in dynamic_tags:
if rewrite:
if full_condition:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
rewrite_file('[' + cond + ']' + m.group(2))
sc.addRuntimeCondition(c)
else:
raise Exception("Unknown tag '" + tag + "' in condition " + cond)
Expand All @@ -308,10 +336,15 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={

# Object - way, node, relation
elif OBJECT.match(css):
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition) + ',\n')
full_condition = ''
if (previous == oDECLARATION):
self.choosers.append(sc)
sc = StyleChooser(self.scalepair)
obj = OBJECT.match(css).groups()[0]
m = OBJECT.match(css)
obj = m.group(1)
rewrite_file(obj + m.group(2))
log.debug("object found: %s" % (obj))
css = OBJECT.sub("", css, 1)
sc.newObject(obj)
Expand All @@ -320,9 +353,16 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={

# Declaration - {...}
elif DECLARATION.match(css):
#previous = oGROUP
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition) + '\n')
#rewrite_file(convert_to_cl(full_condition) + ',\n')
full_condition = ''
if previous == oDECLARATION or previous == oNONE:
raise Exception("Declaration without conditions")
decl = DECLARATION.match(css).groups()[0]
m = DECLARATION.match(css)
rewrite_file(m.group(0))
decl = m.group(1)
log.debug("declaration found: %s" % (decl))
sc.addStyles(self.subst_variables(parseDeclaration(decl)))
css = DECLARATION.sub("", css, 1)
Expand All @@ -331,27 +371,35 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={
# CSS comment
elif COMMENT.match(css):
log.debug("comment found")
rewrite_file(COMMENT.match(css).group(0))
css = COMMENT.sub("", css, 1)

# @import("filename.css");
elif IMPORT.match(css):
m = IMPORT.match(css)
rewrite_file(m.group(0))
log.debug("import found")
import_filename = os.path.join(basepath, IMPORT.match(css).groups()[0])
import_filename = os.path.join(basepath, m.group(1))
try:
css = IMPORT.sub("", css, 1)
import_text = open(import_filename, "r").read()
stck[-1][1] = css # store remained part
stck.append([import_filename, import_text, import_text])
if rewrite:
out_file.close()
out_file = open(stck[-1][0], 'w')
wasBroken = True
break
except IOError as e:
raise Exception("Cannot import file " + import_filename + "\n" + str(e))

# Variables
elif VARIABLE_SET.match(css):
name = VARIABLE_SET.match(css).groups()[0]
m = VARIABLE_SET.match(css)
rewrite_file(m.group(0))
name = m.group(1)
log.debug("variable set found: %s" % name)
self.variables[name] = VARIABLE_SET.match(css).groups()[1]
self.variables[name] = m.group(2)
css = VARIABLE_SET.sub("", css, 1)
previous = oVARIABLE_SET

Expand All @@ -367,11 +415,18 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={

if not wasBroken:
stck.pop()
if rewrite:
out_file.close()
if (len(stck) > 0):
out_file = open(stck[-1][0], 'a')

if (previous == oDECLARATION):
self.choosers.append(sc)
sc = StyleChooser(self.scalepair)

if rewrite:
out_file.close()

except Exception as e:
filename = stck[-1][0] # filename
css_orig = stck[-1][2] # original
Expand All @@ -380,26 +435,6 @@ def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={
msg = str(e) + "\nFile: " + filename + "\nLine: " + str(line)
raise Exception(msg)

try:
if clamp:
"clamp z-indexes, so they're tightly following integers"
zindex = set()
for chooser in self.choosers:
for stylez in chooser.styles:
zindex.add(float(stylez.get('z-index', 0)))
zindex = list(zindex)
zindex.sort()
for chooser in self.choosers:
for stylez in chooser.styles:
if 'z-index' in stylez:
res = zindex.index(float(stylez.get('z-index', 0)))
if stretch:
stylez['z-index'] = stretch * res / len(zindex)
else:
stylez['z-index'] = res
except TypeError:
pass

for chooser in self.choosers:
for t in chooser.compatible_types:
if t not in self.choosers_by_type:
Expand Down