Index: trunk/src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 10373)
+++ trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 10374)
@@ -1183,4 +1183,7 @@
     };
 
+    /**
+     * Destroy this map view panel. Should be called once when it is not needed any more.
+     */
     public void destroy() {
         layerManager.removeLayerChangeListener(this);
@@ -1196,4 +1199,5 @@
             temporaryLayers.clear();
         }
+        nonChangedLayersBuffer = null;
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/BoxTextElement.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/BoxTextElement.java	(revision 10373)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/BoxTextElement.java	(revision 10374)
@@ -22,12 +22,28 @@
 public class BoxTextElement extends StyleElement {
 
+    /**
+     * MapCSS text-anchor-horizontal
+     */
     public enum HorizontalTextAlignment { LEFT, CENTER, RIGHT }
 
+    /**
+     * MapCSS text-anchor-vertical
+     */
     public enum VerticalTextAlignment { ABOVE, TOP, CENTER, BOTTOM, BELOW }
 
+    /**
+     * Something that provides us with a {@link BoxProviderResult}
+     */
     public interface BoxProvider {
+        /**
+         * Compute and get the {@link BoxProviderResult}. The temporary flag is set if the result of the computation may change in the future.
+         * @return The result of the computation.
+         */
         BoxProviderResult get();
     }
 
+    /**
+     * A box rectangle with a flag if it is temporary.
+     */
     public static class BoxProviderResult {
         private final Rectangle box;
@@ -56,4 +72,7 @@
     }
 
+    /**
+     * A {@link BoxProvider} that always returns the same non-temporary rectangle
+     */
     public static class SimpleBoxProvider implements BoxProvider {
         private final Rectangle box;
@@ -86,6 +105,34 @@
     }
 
+    /**
+     * A rectangle with size 0x0
+     */
     public static final Rectangle ZERO_BOX = new Rectangle(0, 0, 0, 0);
 
+    /**
+     * The default style a simple node should use for it's text
+     */
+    public static final BoxTextElement SIMPLE_NODE_TEXT_ELEMSTYLE;
+    static {
+        MultiCascade mc = new MultiCascade();
+        Cascade c = mc.getOrCreateCascade("default");
+        c.put(TEXT, Keyword.AUTO);
+        Node n = new Node();
+        n.put("name", "dummy");
+        SIMPLE_NODE_TEXT_ELEMSTYLE = create(new Environment(n, mc, "default", null), NodeElement.SIMPLE_NODE_ELEMSTYLE.getBoxProvider());
+        if (SIMPLE_NODE_TEXT_ELEMSTYLE == null) throw new AssertionError();
+    }
+
+    /**
+     * Caches the default text color from the preferences.
+     *
+     * FIXME: the cache isn't updated if the user changes the preference during a JOSM
+     * session. There should be preference listener updating this cache.
+     */
+    private static volatile Color defaultTextColorCache;
+
+    /**
+     * The text this element should display.
+     */
     public TextLabel text;
     // Either boxProvider or box is not null. If boxProvider is different from
@@ -94,7 +141,22 @@
     protected BoxProvider boxProvider;
     protected Rectangle box;
+    /**
+     * The {@link HorizontalTextAlignment} for this text.
+     */
     public HorizontalTextAlignment hAlign;
+    /**
+     * The {@link VerticalTextAlignment} for this text.
+     */
     public VerticalTextAlignment vAlign;
 
+    /**
+     * Create a new {@link BoxTextElement}
+     * @param c The current cascade
+     * @param text The text to display
+     * @param boxProvider The box provider to use
+     * @param box The initial box to use.
+     * @param hAlign The {@link HorizontalTextAlignment}
+     * @param vAlign The {@link VerticalTextAlignment}
+     */
     public BoxTextElement(Cascade c, TextLabel text, BoxProvider boxProvider, Rectangle box,
             HorizontalTextAlignment hAlign, VerticalTextAlignment vAlign) {
@@ -110,16 +172,35 @@
     }
 
+    /**
+     * Create a new {@link BoxTextElement} with a dynamic box
+     * @param env The MapCSS environment
+     * @param boxProvider The box provider that computes the box.
+     * @return A new {@link BoxTextElement} or <code>null</code> if the creation failed.
+     */
     public static BoxTextElement create(Environment env, BoxProvider boxProvider) {
         return create(env, boxProvider, null);
     }
 
+    /**
+     * Create a new {@link BoxTextElement} with a fixed box
+     * @param env The MapCSS environment
+     * @param box The box
+     * @return A new {@link BoxTextElement} or <code>null</code> if the creation failed.
+     */
     public static BoxTextElement create(Environment env, Rectangle box) {
         return create(env, null, box);
     }
 
+    /**
+     * Create a new {@link BoxTextElement} with a boxprovider and a box.
+     * @param env The MapCSS environment
+     * @param boxProvider The box provider.
+     * @param box The box. Only considered if boxProvider is null.
+     * @return A new {@link BoxTextElement} or <code>null</code> if the creation failed.
+     */
     public static BoxTextElement create(Environment env, BoxProvider boxProvider, Rectangle box) {
         initDefaultParameters();
 
-        TextLabel text = TextLabel.create(env, DEFAULT_TEXT_COLOR, false);
+        TextLabel text = TextLabel.create(env, defaultTextColorCache, false);
         if (text == null) return null;
         // Skip any primitives that don't have text to draw. (Styles are recreated for any tag change.)
@@ -164,4 +245,8 @@
     }
 
+    /**
+     * Get the box in which the content should be drawn.
+     * @return The box.
+     */
     public Rectangle getBox() {
         if (boxProvider != null) {
@@ -176,26 +261,8 @@
     }
 
-    public static final BoxTextElement SIMPLE_NODE_TEXT_ELEMSTYLE;
-    static {
-        MultiCascade mc = new MultiCascade();
-        Cascade c = mc.getOrCreateCascade("default");
-        c.put(TEXT, Keyword.AUTO);
-        Node n = new Node();
-        n.put("name", "dummy");
-        SIMPLE_NODE_TEXT_ELEMSTYLE = create(new Environment(n, mc, "default", null), NodeElement.SIMPLE_NODE_ELEMSTYLE.getBoxProvider());
-        if (SIMPLE_NODE_TEXT_ELEMSTYLE == null) throw new AssertionError();
-    }
-
-    /*
-     * Caches the default text color from the preferences.
-     *
-     * FIXME: the cache isn't updated if the user changes the preference during a JOSM
-     * session. There should be preference listener updating this cache.
-     */
-    private static volatile Color DEFAULT_TEXT_COLOR;
 
     private static void initDefaultParameters() {
-        if (DEFAULT_TEXT_COLOR != null) return;
-        DEFAULT_TEXT_COLOR = PaintColors.TEXT.get();
+        if (defaultTextColorCache != null) return;
+        defaultTextColorCache = PaintColors.TEXT.get();
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineElement.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineElement.java	(revision 10373)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineElement.java	(revision 10374)
@@ -21,19 +21,11 @@
 import org.openstreetmap.josm.tools.Utils;
 
+/**
+ * This is the style definition for a simple line.
+ */
 public class LineElement extends StyleElement {
-
-    public static LineElement createSimpleLineStyle(Color color, boolean isAreaEdge) {
-        MultiCascade mc = new MultiCascade();
-        Cascade c = mc.getOrCreateCascade("default");
-        c.put(WIDTH, Keyword.DEFAULT);
-        c.put(COLOR, color != null ? color : PaintColors.UNTAGGED.get());
-        c.put(OPACITY, 1f);
-        if (isAreaEdge) {
-            c.put(Z_INDEX, -3f);
-        }
-        Way w = new Way();
-        return createLine(new Environment(w, mc, "default", null));
-    }
-
+    /**
+     * The default style for any untagged way.
+     */
     public static final LineElement UNTAGGED_WAY = createSimpleLineStyle(null, false);
 
@@ -72,203 +64,4 @@
         this.realWidth = realWidth;
         this.wayDirectionArrows = wayDirectionArrows;
-    }
-
-    public static LineElement createLine(Environment env) {
-        return createImpl(env, LineType.NORMAL);
-    }
-
-    public static LineElement createLeftCasing(Environment env) {
-        LineElement leftCasing = createImpl(env, LineType.LEFT_CASING);
-        if (leftCasing != null) {
-            leftCasing.isModifier = true;
-        }
-        return leftCasing;
-    }
-
-    public static LineElement createRightCasing(Environment env) {
-        LineElement rightCasing = createImpl(env, LineType.RIGHT_CASING);
-        if (rightCasing != null) {
-            rightCasing.isModifier = true;
-        }
-        return rightCasing;
-    }
-
-    public static LineElement createCasing(Environment env) {
-        LineElement casing = createImpl(env, LineType.CASING);
-        if (casing != null) {
-            casing.isModifier = true;
-        }
-        return casing;
-    }
-
-    private static LineElement createImpl(Environment env, LineType type) {
-        Cascade c = env.mc.getCascade(env.layer);
-        Cascade cDef = env.mc.getCascade("default");
-        Float width;
-        switch (type) {
-            case NORMAL:
-                width = getWidth(c, WIDTH, getWidth(cDef, WIDTH, null));
-                break;
-            case CASING:
-                Float casingWidth = c.get(type.prefix + WIDTH, null, Float.class, true);
-                if (casingWidth == null) {
-                    RelativeFloat relCasingWidth = c.get(type.prefix + WIDTH, null, RelativeFloat.class, true);
-                    if (relCasingWidth != null) {
-                        casingWidth = relCasingWidth.val / 2;
-                    }
-                }
-                if (casingWidth == null)
-                    return null;
-                width = getWidth(c, WIDTH, getWidth(cDef, WIDTH, null));
-                if (width == null) {
-                    width = 0f;
-                }
-                width += 2 * casingWidth;
-                break;
-            case LEFT_CASING:
-            case RIGHT_CASING:
-                width = getWidth(c, type.prefix + WIDTH, null);
-                break;
-            default:
-                throw new AssertionError();
-        }
-        if (width == null)
-            return null;
-
-        float realWidth = c.get(type.prefix + REAL_WIDTH, 0f, Float.class);
-        if (realWidth > 0 && MapPaintSettings.INSTANCE.isUseRealWidth()) {
-
-            /* if we have a "width" tag, try use it */
-            String widthTag = env.osm.get("width");
-            if (widthTag == null) {
-                widthTag = env.osm.get("est_width");
-            }
-            if (widthTag != null) {
-                try {
-                    realWidth = Float.parseFloat(widthTag);
-                } catch (NumberFormatException nfe) {
-                    Main.warn(nfe);
-                }
-            }
-        }
-
-        Float offset = c.get(OFFSET, 0f, Float.class);
-        switch (type) {
-            case NORMAL:
-                break;
-            case CASING:
-                offset += c.get(type.prefix + OFFSET, 0f, Float.class);
-                break;
-            case LEFT_CASING:
-            case RIGHT_CASING:
-                Float baseWidthOnDefault = getWidth(cDef, WIDTH, null);
-                Float baseWidth = getWidth(c, WIDTH, baseWidthOnDefault);
-                if (baseWidth == null || baseWidth < 2f) {
-                    baseWidth = 2f;
-                }
-                float casingOffset = c.get(type.prefix + OFFSET, 0f, Float.class);
-                casingOffset += baseWidth / 2 + width / 2;
-                /* flip sign for the right-casing-offset */
-                if (type == LineType.RIGHT_CASING) {
-                    casingOffset *= -1f;
-                }
-                offset += casingOffset;
-                break;
-        }
-
-        int alpha = 255;
-        Color color = c.get(type.prefix + COLOR, null, Color.class);
-        if (color != null) {
-            alpha = color.getAlpha();
-        }
-        if (type == LineType.NORMAL && color == null) {
-            color = c.get(FILL_COLOR, null, Color.class);
-        }
-        if (color == null) {
-            color = PaintColors.UNTAGGED.get();
-        }
-
-        Integer pAlpha = Utils.color_float2int(c.get(type.prefix + OPACITY, null, Float.class));
-        if (pAlpha != null) {
-            alpha = pAlpha;
-        }
-        color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
-
-        float[] dashes = c.get(type.prefix + DASHES, null, float[].class, true);
-        if (dashes != null) {
-            boolean hasPositive = false;
-            for (float f : dashes) {
-                if (f > 0) {
-                    hasPositive = true;
-                }
-                if (f < 0) {
-                    dashes = null;
-                    break;
-                }
-            }
-            if (!hasPositive || (dashes != null && dashes.length == 0)) {
-                dashes = null;
-            }
-        }
-        float dashesOffset = c.get(type.prefix + DASHES_OFFSET, 0f, Float.class);
-        Color dashesBackground = c.get(type.prefix + DASHES_BACKGROUND_COLOR, null, Color.class);
-        if (dashesBackground != null) {
-            pAlpha = Utils.color_float2int(c.get(type.prefix + DASHES_BACKGROUND_OPACITY, null, Float.class));
-            if (pAlpha != null) {
-                alpha = pAlpha;
-            }
-            dashesBackground = new Color(dashesBackground.getRed(), dashesBackground.getGreen(),
-                    dashesBackground.getBlue(), alpha);
-        }
-
-        Integer cap = null;
-        Keyword capKW = c.get(type.prefix + LINECAP, null, Keyword.class);
-        if (capKW != null) {
-            if ("none".equals(capKW.val)) {
-                cap = BasicStroke.CAP_BUTT;
-            } else if ("round".equals(capKW.val)) {
-                cap = BasicStroke.CAP_ROUND;
-            } else if ("square".equals(capKW.val)) {
-                cap = BasicStroke.CAP_SQUARE;
-            }
-        }
-        if (cap == null) {
-            cap = dashes != null ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
-        }
-
-        Integer join = null;
-        Keyword joinKW = c.get(type.prefix + LINEJOIN, null, Keyword.class);
-        if (joinKW != null) {
-            if ("round".equals(joinKW.val)) {
-                join = BasicStroke.JOIN_ROUND;
-            } else if ("miter".equals(joinKW.val)) {
-                join = BasicStroke.JOIN_MITER;
-            } else if ("bevel".equals(joinKW.val)) {
-                join = BasicStroke.JOIN_BEVEL;
-            }
-        }
-        if (join == null) {
-            join = BasicStroke.JOIN_ROUND;
-        }
-
-        float miterlimit = c.get(type.prefix + MITERLIMIT, 10f, Float.class);
-        if (miterlimit < 1f) {
-            miterlimit = 10f;
-        }
-
-        BasicStroke line = new BasicStroke(width, cap, join, miterlimit, dashes, dashesOffset);
-        BasicStroke dashesLine = null;
-
-        if (dashes != null && dashesBackground != null) {
-            float[] dashes2 = new float[dashes.length];
-            System.arraycopy(dashes, 0, dashes2, 1, dashes.length - 1);
-            dashes2[0] = dashes[dashes.length-1];
-            dashesLine = new BasicStroke(width, cap, join, miterlimit, dashes2, dashes2[0] + dashesOffset);
-        }
-
-        boolean wayDirectionArrows = c.get(type.prefix + WAY_DIRECTION_ARROWS, env.osm.isSelected(), Boolean.class);
-
-        return new LineElement(c, type.defaultMajorZIndex, line, color, dashesLine, dashesBackground,
-                offset, realWidth, wayDirectionArrows);
     }
 
@@ -339,4 +132,22 @@
     public boolean isProperLineStyle() {
         return !isModifier;
+    }
+
+    public String linejoinToString(int linejoin) {
+        switch (linejoin) {
+            case BasicStroke.JOIN_BEVEL: return "bevel";
+            case BasicStroke.JOIN_ROUND: return "round";
+            case BasicStroke.JOIN_MITER: return "miter";
+            default: return null;
+        }
+    }
+
+    public String linecapToString(int linecap) {
+        switch (linecap) {
+            case BasicStroke.CAP_BUTT: return "none";
+            case BasicStroke.CAP_ROUND: return "round";
+            case BasicStroke.CAP_SQUARE: return "square";
+            default: return null;
+        }
     }
 
@@ -375,20 +186,235 @@
     }
 
-    public String linejoinToString(int linejoin) {
-        switch (linejoin) {
-            case BasicStroke.JOIN_BEVEL: return "bevel";
-            case BasicStroke.JOIN_ROUND: return "round";
-            case BasicStroke.JOIN_MITER: return "miter";
-            default: return null;
-        }
-    }
-
-    public String linecapToString(int linecap) {
-        switch (linecap) {
-            case BasicStroke.CAP_BUTT: return "none";
-            case BasicStroke.CAP_ROUND: return "round";
-            case BasicStroke.CAP_SQUARE: return "square";
-            default: return null;
-        }
+    /**
+     * Creates a simple line with default widt.
+     * @param color The color to use
+     * @param isAreaEdge If this is an edge for an area. Edges are drawn at lower Z-Index.
+     * @return The line style.
+     */
+    public static LineElement createSimpleLineStyle(Color color, boolean isAreaEdge) {
+        MultiCascade mc = new MultiCascade();
+        Cascade c = mc.getOrCreateCascade("default");
+        c.put(WIDTH, Keyword.DEFAULT);
+        c.put(COLOR, color != null ? color : PaintColors.UNTAGGED.get());
+        c.put(OPACITY, 1f);
+        if (isAreaEdge) {
+            c.put(Z_INDEX, -3f);
+        }
+        Way w = new Way();
+        return createLine(new Environment(w, mc, "default", null));
+    }
+
+    public static LineElement createLine(Environment env) {
+        return createImpl(env, LineType.NORMAL);
+    }
+
+    public static LineElement createLeftCasing(Environment env) {
+        LineElement leftCasing = createImpl(env, LineType.LEFT_CASING);
+        if (leftCasing != null) {
+            leftCasing.isModifier = true;
+        }
+        return leftCasing;
+    }
+
+    public static LineElement createRightCasing(Environment env) {
+        LineElement rightCasing = createImpl(env, LineType.RIGHT_CASING);
+        if (rightCasing != null) {
+            rightCasing.isModifier = true;
+        }
+        return rightCasing;
+    }
+
+    public static LineElement createCasing(Environment env) {
+        LineElement casing = createImpl(env, LineType.CASING);
+        if (casing != null) {
+            casing.isModifier = true;
+        }
+        return casing;
+    }
+
+    private static LineElement createImpl(Environment env, LineType type) {
+        Cascade c = env.mc.getCascade(env.layer);
+        Cascade cDef = env.mc.getCascade("default");
+        Float width = computeWidth(type, c, cDef);
+        if (width == null)
+            return null;
+
+        float realWidth = computeRealWidth(env, type, c);
+
+        Float offset = computeOffset(type, c, cDef, width);
+
+        int alpha = 255;
+        Color color = c.get(type.prefix + COLOR, null, Color.class);
+        if (color != null) {
+            alpha = color.getAlpha();
+        }
+        if (type == LineType.NORMAL && color == null) {
+            color = c.get(FILL_COLOR, null, Color.class);
+        }
+        if (color == null) {
+            color = PaintColors.UNTAGGED.get();
+        }
+
+        Integer pAlpha = Utils.color_float2int(c.get(type.prefix + OPACITY, null, Float.class));
+        if (pAlpha != null) {
+            alpha = pAlpha;
+        }
+        color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
+
+        float[] dashes = c.get(type.prefix + DASHES, null, float[].class, true);
+        if (dashes != null) {
+            boolean hasPositive = false;
+            for (float f : dashes) {
+                if (f > 0) {
+                    hasPositive = true;
+                }
+                if (f < 0) {
+                    dashes = null;
+                    break;
+                }
+            }
+            if (!hasPositive || (dashes != null && dashes.length == 0)) {
+                dashes = null;
+            }
+        }
+        float dashesOffset = c.get(type.prefix + DASHES_OFFSET, 0f, Float.class);
+        Color dashesBackground = c.get(type.prefix + DASHES_BACKGROUND_COLOR, null, Color.class);
+        if (dashesBackground != null) {
+            pAlpha = Utils.color_float2int(c.get(type.prefix + DASHES_BACKGROUND_OPACITY, null, Float.class));
+            if (pAlpha != null) {
+                alpha = pAlpha;
+            }
+            dashesBackground = new Color(dashesBackground.getRed(), dashesBackground.getGreen(),
+                    dashesBackground.getBlue(), alpha);
+        }
+
+        Integer cap = null;
+        Keyword capKW = c.get(type.prefix + LINECAP, null, Keyword.class);
+        if (capKW != null) {
+            if ("none".equals(capKW.val)) {
+                cap = BasicStroke.CAP_BUTT;
+            } else if ("round".equals(capKW.val)) {
+                cap = BasicStroke.CAP_ROUND;
+            } else if ("square".equals(capKW.val)) {
+                cap = BasicStroke.CAP_SQUARE;
+            }
+        }
+        if (cap == null) {
+            cap = dashes != null ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
+        }
+
+        Integer join = null;
+        Keyword joinKW = c.get(type.prefix + LINEJOIN, null, Keyword.class);
+        if (joinKW != null) {
+            if ("round".equals(joinKW.val)) {
+                join = BasicStroke.JOIN_ROUND;
+            } else if ("miter".equals(joinKW.val)) {
+                join = BasicStroke.JOIN_MITER;
+            } else if ("bevel".equals(joinKW.val)) {
+                join = BasicStroke.JOIN_BEVEL;
+            }
+        }
+        if (join == null) {
+            join = BasicStroke.JOIN_ROUND;
+        }
+
+        float miterlimit = c.get(type.prefix + MITERLIMIT, 10f, Float.class);
+        if (miterlimit < 1f) {
+            miterlimit = 10f;
+        }
+
+        BasicStroke line = new BasicStroke(width, cap, join, miterlimit, dashes, dashesOffset);
+        BasicStroke dashesLine = null;
+
+        if (dashes != null && dashesBackground != null) {
+            float[] dashes2 = new float[dashes.length];
+            System.arraycopy(dashes, 0, dashes2, 1, dashes.length - 1);
+            dashes2[0] = dashes[dashes.length-1];
+            dashesLine = new BasicStroke(width, cap, join, miterlimit, dashes2, dashes2[0] + dashesOffset);
+        }
+
+        boolean wayDirectionArrows = c.get(type.prefix + WAY_DIRECTION_ARROWS, env.osm.isSelected(), Boolean.class);
+
+        return new LineElement(c, type.defaultMajorZIndex, line, color, dashesLine, dashesBackground,
+                offset, realWidth, wayDirectionArrows);
+    }
+
+    private static Float computeWidth(LineType type, Cascade c, Cascade cDef) {
+        Float width;
+        switch (type) {
+            case NORMAL:
+                width = getWidth(c, WIDTH, getWidth(cDef, WIDTH, null));
+                break;
+            case CASING:
+                Float casingWidth = c.get(type.prefix + WIDTH, null, Float.class, true);
+                if (casingWidth == null) {
+                    RelativeFloat relCasingWidth = c.get(type.prefix + WIDTH, null, RelativeFloat.class, true);
+                    if (relCasingWidth != null) {
+                        casingWidth = relCasingWidth.val / 2;
+                    }
+                }
+                if (casingWidth == null)
+                    return null;
+                width = getWidth(c, WIDTH, getWidth(cDef, WIDTH, null));
+                if (width == null) {
+                    width = 0f;
+                }
+                width += 2 * casingWidth;
+                break;
+            case LEFT_CASING:
+            case RIGHT_CASING:
+                width = getWidth(c, type.prefix + WIDTH, null);
+                break;
+            default:
+                throw new AssertionError();
+        }
+        return width;
+    }
+
+    private static float computeRealWidth(Environment env, LineType type, Cascade c) {
+        float realWidth = c.get(type.prefix + REAL_WIDTH, 0f, Float.class);
+        if (realWidth > 0 && MapPaintSettings.INSTANCE.isUseRealWidth()) {
+
+            /* if we have a "width" tag, try use it */
+            String widthTag = env.osm.get("width");
+            if (widthTag == null) {
+                widthTag = env.osm.get("est_width");
+            }
+            if (widthTag != null) {
+                try {
+                    realWidth = Float.parseFloat(widthTag);
+                } catch (NumberFormatException nfe) {
+                    Main.warn(nfe);
+                }
+            }
+        }
+        return realWidth;
+    }
+
+    private static Float computeOffset(LineType type, Cascade c, Cascade cDef, Float width) {
+        Float offset = c.get(OFFSET, 0f, Float.class);
+        switch (type) {
+            case NORMAL:
+                break;
+            case CASING:
+                offset += c.get(type.prefix + OFFSET, 0f, Float.class);
+                break;
+            case LEFT_CASING:
+            case RIGHT_CASING:
+                Float baseWidthOnDefault = getWidth(cDef, WIDTH, null);
+                Float baseWidth = getWidth(c, WIDTH, baseWidthOnDefault);
+                if (baseWidth == null || baseWidth < 2f) {
+                    baseWidth = 2f;
+                }
+                float casingOffset = c.get(type.prefix + OFFSET, 0f, Float.class);
+                casingOffset += baseWidth / 2 + width / 2;
+                /* flip sign for the right-casing-offset */
+                if (type == LineType.RIGHT_CASING) {
+                    casingOffset *= -1f;
+                }
+                offset += casingOffset;
+                break;
+        }
+        return offset;
     }
 }
