From 367da7e6762806a4360b8d6285a54b841eea24f1 Mon Sep 17 00:00:00 2001
From: Viktor Govako <viktor.govako@gmail.com>
Date: Fri, 5 Nov 2021 13:28:40 +0100
Subject: [PATCH 1/2] Added -x-me-min-text-priority hack.

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
---
 src/libkomwm.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/libkomwm.py b/src/libkomwm.py
index c598b5f..c9af8d6 100644
--- a/src/libkomwm.py
+++ b/src/libkomwm.py
@@ -353,7 +353,7 @@ def komap_mapswithme(options):
                         if has_fills and 'fill-color' in st and float(st.get('fill-opacity', 1)) > 0:
                             dr_element.area.border.color = mwm_encode_color(colors, st, "casing")
                             dr_element.area.border.width = st.get('casing-width', 0) * WIDTH_SCALE
-                            
+
                         # 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()
@@ -462,10 +462,15 @@ def komap_mapswithme(options):
                                 else:
                                     dr_cur_subtext.is_optional = True
                             has_text.pop()
+
                         if '-x-me-text-priority' in st:
                             dr_text.priority = int(st.get('-x-me-text-priority'))
                         else:
                             dr_text.priority = min(19000, (base_z + int(st.get('z-index', 0))))
+                        if '-x-me-min-text-priority' in st:
+                            min_priority = int(st.get('-x-me-min-text-priority'))
+                            dr_text.priority = max(min_priority, dr_text.priority)
+
                         has_text = None
 
                     if has_fills:
-- 
2.45.3


From 89b59de837d5751c3247cd20a803b55a7b320f05 Mon Sep 17 00:00:00 2001
From: Viktor Govako <viktor.govako@gmail.com>
Date: Mon, 16 May 2022 17:06:19 +0300
Subject: [PATCH 2/2] Python3 migration.

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
---
 src/libkomwm.py    | 46 +++++++++++++++++++++++++++++++++-------------
 src/mapcss/Eval.py | 18 ++++++++++++++++--
 2 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/src/libkomwm.py b/src/libkomwm.py
index c9af8d6..d002ff7 100644
--- a/src/libkomwm.py
+++ b/src/libkomwm.py
@@ -3,11 +3,11 @@ from optparse import OptionParser
 import os
 import csv
 import sys
-import itertools
 import functools
-from multiprocessing import Pool
+from multiprocessing import Pool, set_start_method
 from collections import OrderedDict
 import mapcss.webcolors
+
 whatever_to_hex = mapcss.webcolors.webcolors.whatever_to_hex
 whatever_to_cairo = mapcss.webcolors.webcolors.whatever_to_cairo
 
@@ -59,6 +59,7 @@ def mwm_encode_image(st, prefix='icon', bgprefix='symbol'):
 
 
 def query_style(args):
+    global style
     cl, cltags, minzoom, maxzoom = args
     clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
 
@@ -260,13 +261,14 @@ def komap_mapswithme(options):
     drules = ContainerProto()
     dr_cont = None
     if MULTIPROCESSING:
+        set_start_method('fork')  # Use fork with multiprocessing to share global variables among Python instances
         pool = Pool()
         imapfunc = pool.imap
     else:
-        imapfunc = itertools.imap
+        imapfunc = map
 
     if style_colors:
-        for k, v in style_colors.items():
+        for k, v in sorted(list(style_colors.items())):
             color_proto = ColorElementProto()
             color_proto.name = k
             color_proto.color = v
@@ -280,6 +282,24 @@ def komap_mapswithme(options):
         for result in results:
                 cl, zoom, has_icons_for_areas, runtime_conditions, zstyle = result
 
+                # First, sort rules by 'object-id' in captions (primary, secondary, none ..);
+                # Then by 'z-index' in ascending order.
+                def rule_sort_key(dict_):
+                    first = 0
+                    if dict_.get('text'):
+                        if str(dict_.get('object-id')) != '::default':
+                            first = 1
+                        if str(dict_.get('text')) == 'none':
+                            first = 2
+                    return (first, int(dict_.get('z-index', 0)))
+
+                zstyle.sort(key = rule_sort_key)
+
+                # For debug purpose.
+                # if str(cl) == 'entrance' and int(zoom) == 19:
+                #     print(cl)
+                #     print(zstyle)
+
                 if dr_cont is not None and dr_cont.name != cl:
                     if dr_cont.element:
                         drules.cont.extend([dr_cont])
@@ -432,19 +452,17 @@ def komap_mapswithme(options):
                             has_icons = False
 
                     if has_text and st.get('text') and st.get('text') != 'none':
+                        # Take only first 2 captions: primary, secondary.
                         has_text = has_text[:2]
-                        has_text.reverse()
-                        dr_text = dr_element.path_text
+
+                        dr_text = dr_element.caption
                         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 = dr_text.primary
+                        for sp in has_text:
                             dr_cur_subtext.height = int(float(sp.get('font-size', "10").split(",")[0]))
                             dr_cur_subtext.color = mwm_encode_color(colors, sp, "text")
                             if st.get('text-halo-radius', 0) != 0:
@@ -461,8 +479,9 @@ def komap_mapswithme(options):
                                     dr_cur_subtext.is_optional = value
                                 else:
                                     dr_cur_subtext.is_optional = True
-                            has_text.pop()
+                            dr_cur_subtext = dr_text.secondary
 
+                        #  Priority is assigned from the first (primary) rule.
                         if '-x-me-text-priority' in st:
                             dr_text.priority = int(st.get('-x-me-text-priority'))
                         else:
@@ -471,6 +490,7 @@ def komap_mapswithme(options):
                             min_priority = int(st.get('-x-me-min-text-priority'))
                             dr_text.priority = max(min_priority, dr_text.priority)
 
+                        # Process captions block once.
                         has_text = None
 
                     if has_fills:
diff --git a/src/mapcss/Eval.py b/src/mapcss/Eval.py
index f48c510..131e6bb 100644
--- a/src/mapcss/Eval.py
+++ b/src/mapcss/Eval.py
@@ -72,7 +72,7 @@ class Eval():
                 pass
         """
         try:
-            return str(eval(self.expr, {}, {
+            result = eval(self.expr, {}, {
                             "tag": lambda x: tags.get(x, ""),
                             "prop": lambda x: props.get(x, ""),
                             "num": m_num,
@@ -84,7 +84,21 @@ class Eval():
                             "max": m_max,
                             "cond": m_cond,
                             "boolean": m_boolean
-                            }))
+                            })
+
+            if type(result) == float:
+                # In Python2 and Python3 float to string behaves differently
+                # Python 2:
+                #   >>> str(2.8 + 0.4)
+                #   '3.2'
+                # Python 3:
+                #   >>> str(2.8 + 0.4)
+                #   '3.1999999999999997'
+                #
+                # See https://stackoverflow.com/q/25898733 for details
+                return "{:.4g}".format(result)
+
+            return str(result)
         except:
             return ""
 
-- 
2.45.3