Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 7169)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 7170)
@@ -15,4 +15,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -29,4 +31,5 @@
 import org.openstreetmap.josm.io.XmlWriter;
 import org.openstreetmap.josm.tools.ColorHelper;
+import org.openstreetmap.josm.tools.Predicates;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -210,40 +213,4 @@
 
         /**
-         * Returns the minimum of the given numbers, or NaN if no number is given.
-         * @see Math#min(float, float)
-         */
-        public static float min(float... args) {
-            if (args.length == 0) {
-                return Float.NaN;
-            } else if (args.length == 1) {
-                return args[0];
-            } else {
-                float min = Math.min(args[0], args[1]);
-                for (int i = 2; i < args.length; i++) {
-                    min = Math.min(min, args[i]);
-                }
-                return min;
-            }
-        }
-
-        /**
-         * Returns the maximum of the given numbers, or NaN if no number is given.
-         * @see Math#max(float, float)
-         */
-        public static float max(float... args) {
-            if (args.length == 0) {
-                return Float.NaN;
-            } else if (args.length == 1) {
-                return args[0];
-            } else {
-                float max = Math.max(args[0], args[1]);
-                for (int i = 2; i < args.length; i++) {
-                    max = Math.max(max, args[i]);
-                }
-                return max;
-            }
-        }
-
-        /**
          * Splits string {@code toSplit} at occurrences of the separator string {@code sep} and returns a list of matches.
          * @see String#split(String)
@@ -673,4 +640,8 @@
         else if ("length".equals(name) && args.size() == 1)
             return new LengthFunction(args.get(0));
+        else if ("max".equals(name) && !args.isEmpty())
+            return new MinMaxFunction(args, true);
+        else if ("min".equals(name) && !args.isEmpty())
+            return new MinMaxFunction(args, false);
 
         for (Method m : arrayFunctions) {
@@ -795,4 +766,42 @@
                 return s.length();
             return null;
+        }
+    }
+
+    /**
+     * Computes the maximum/minimum value an arbitrary number of floats, or a list of floats.
+     */
+    public static class MinMaxFunction implements Expression {
+
+        private final List<Expression> args;
+        private final boolean computeMax;
+
+        public MinMaxFunction(final List<Expression> args, final boolean computeMax) {
+            this.args = args;
+            this.computeMax = computeMax;
+        }
+
+        public Float aggregateList(List<?> lst) {
+            final List<Float> floats = Utils.transform(lst, new Utils.Function<Object, Float>() {
+                @Override
+                public Float apply(Object x) {
+                    return Cascade.convertTo(x, float.class);
+                }
+            });
+            final Collection<Float> nonNullList = Utils.filter(floats, Predicates.not(Predicates.isNull()));
+            return computeMax ? Collections.max(nonNullList) : Collections.min(nonNullList);
+        }
+
+        @Override
+        public Object evaluate(final Environment env) {
+            List<?> l = Cascade.convertTo(args.get(0).evaluate(env), List.class);
+            if (args.size() != 1 || l == null)
+                l = Utils.transform(args, new Utils.Function<Expression, Object>() {
+                    @Override
+                    public Object apply(Expression x) {
+                        return x.evaluate(env);
+                    }
+                });
+            return aggregateList(l);
         }
     }
Index: trunk/src/org/openstreetmap/josm/tools/Predicates.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Predicates.java	(revision 7169)
+++ trunk/src/org/openstreetmap/josm/tools/Predicates.java	(revision 7170)
@@ -28,5 +28,5 @@
 
     /**
-     * Returns a {@link Predicate} executing {@link Utils#equal}.
+     * Returns a {@link Predicate} executing {@link Objects#equals}.
      */
     public static <T> Predicate<T> equalTo(final T ref) {
@@ -110,3 +110,15 @@
         };
     }
+
+    /**
+     * Returns a {@link Predicate} testing whether objects are {@code null}.
+     */
+    public static <T> Predicate<T> isNull() {
+        return new Predicate<T>() {
+            @Override
+            public boolean evaluate(T object) {
+                return object == null;
+            }
+        };
+    }
 }
Index: trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.groovy
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.groovy	(revision 7169)
+++ trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.groovy	(revision 7170)
@@ -353,4 +353,5 @@
                 "min_value: min(tag(x), tag(y), tag(z)); " +
                 "max_value: max(tag(x), tag(y), tag(z)); " +
+                "max_split: max(split(\";\", tag(widths))); " +
                 "}")
         sheet.loadStyleSource()
@@ -361,7 +362,8 @@
         assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_value", Float.NaN, Float.class) == 8.0f
 
-        sheet.apply(mc, TestUtils.createPrimitive("way x=4 y=6"), 20, null, false)
-        assert mc.getCascade(Environment.DEFAULT_LAYER).get("min_value", -777f, Float.class) == -777f
-        assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_value", -777f, Float.class) == -777f
+        sheet.apply(mc, TestUtils.createPrimitive("way x=4 y=6 widths=1;2;8;56;3;a"), 20, null, false)
+        assert mc.getCascade(Environment.DEFAULT_LAYER).get("min_value", -777f, Float.class) == 4
+        assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_value", -777f, Float.class) == 6
+        assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_split", -777f, Float.class) == 56
     }
 }
