[Mapcss] Development of MapCSS?

Martin Vonwald imagic.osm at gmail.com
Sat Mar 9 10:39:58 UTC 2013

Hi all,

I had some thoughts lately about how to improve MapCSS.

First I quickly compared the MapCSS specification with the JOSM
implementation. JOSM implements a lot more than specified and many of
them are really useful. Namely:
* all the "symbol-" properties
* text-anchor-....
* dashes-....
* The suffix casing applies to more keys than in MapCSS. Furthermore
JOSM supports also left-casing-... and right-casing-...
* text-halo-opacity
* A lot more built-in functions for eval. See below for further
comments on this.
Most of them I have already used.

There are also some major difference between the specification and the
JOSM implementation:
* z-index: MapCSS specifies this only for lines, while JOSM interprets
this for all objects. The latter makes much more sense IMO.
* text-offset is also supported as text-offset-y in JOSM; furthermore
there is a property text-offset-x, but I don't really can think of a
use-case for this.
* The child and link selectors from JOSM seem to be the combining
selectors from MapCSS. Parent selectors are missing from MapCSS (I
think). In my opinion the syntax of JOSM for child and link selectors
is better readable than the combining selectors of MapCSS.
* In MapCSS the testing for truth values is not specified, e.g.
way[oneway?], which comes in handy quite often.
* The MapCSS specifications seems to lack the property "offset" from
JOSM, which moves the line left or right. This is a very important
* Some more listed in the Compatibility notes of JOSM

Not implemented in JOSM so far are:
* Shield properties. I could use them e.g. for traffic signs... maybe.
* Some label properties like font-variant, text-decoration,
text-transform, max-width. Seems like "nice-to-have" to me.
* The property "image" seems(!) to be implemented as "pattern-image".
I'm not really sure about this, because the MapCSS documentation is a
little short there.
* The pseudo-classes :hover and :active are not supported, which would
allow different rendering for selected objects. I'm definitively
missing those.

I could think of the following improvements to rendering capabilities:
* Line image: I'm missing the possibility to specify an offset for the
image (for each layer!) to precisely place the image. Something like
image-offset, which should be consistent with the offset property from
* The MapCSS specification is not clear in the case fill-color AND
fill-image are specified at the same time. JOSM seems to ignore the
color if a image is specified. In my opinion it would make much sense
if both is allowed at the same time and the color is drawn below the
image. Think of partially transparent images, which then can be used
for different purposes without always adding a separate layer.
* A property like text-repeat (for lines) with values like yes, no and
cut. The value "no" is the default and text is rendered just like in
the current specification. If the value is "yes" the text should start
at the left end of the line (or right end if the text is written from
right to left) and should be repeated until the right end (or left end
for right-to-left); if necessary it should be cut. The value "cut"
differs from the value "yes" by even showing the text if it is too
long for the line, but it will be cut to fit.
* The specified "text-offset" can not be used to place a text
accurately. It specifies that the text is written either above or
below the line, which means that e.g. a text is written on the left
side of the line if the line runs from left to right and on the right
side of the line if the same line now runs from right to left. There
should be a text-property which works precisely as the property offset
from JOSM. (But the text itself should never be written upside-down.)

Improvements needed to process data:
Obviously from the number of built-in functions in JOSM there is a
strong need of more processing capabilities. Arrays, loops, nested if
statements are just a few of them. As I'm not really a fan of
reinventing the wheel again and again I want to suggest something and
hear your opinions. Here's an example which should make clear what I
have in mind:

   some_setting: true;

    turn_list: eval(split("|",tag("turn:lanes")));   <--- uses some
josm-function; doesn't matter for the example
    markings: "";

script @ way[turn:lanes]::Layer   <---- "script @": the following is javascript
   var setting=getProperty("some_setting","default");    <---- Another
layer: we need getProperty
   markings=new Array(turn_list.length);                      <----
turn_list is on the same layer
   for (int i=0;i<turn_list.length;i++)
      if (turn_list[i]=="left") markings[i]="left.png";
}    <--- properties may have been changed by the script, but no new
properties are set, i.e. "setting" is not a property of the layer

    image: eval(get(markings,0));   <---- the property markings was
filled by the script

If we do it like this all complex processing can be put into
script-blocks. We could reuse javascript for which interpreters are
available in the programming languages of our major editors if I'm not
mistaken. But there is still one problem: the script part might return
a list of properties and we need to create for each entry a separate
layer. To solve this I was thinking of the following but I'm not
really happy with it:

iterate(index,"markings","Layer") @  way[turn:lanes]::Lane_[index]
   image-offset: eval(prop(index) * 20);
   image: eval(prop(iterate_markings));


This can be read as: if we have a way with turn:lanes set, iterate
over the list "markings" from the layer "Layer", put the index of the
iteration into "index" and create a layer "Lane_<index>" for this. The
property "index" would be available in that layer. I doesn't really
like how that looks like, but I can't think of a better solution right

I think this is enough to make everyone thinking over the next days,
so I'll stop here ;-)

Have a nice weekend,

More information about the Mapcss mailing list