diff -r 737377b8ab1d javafx-ui-common/src/javafx/scene/layout/FlowPane.java
--- a/javafx-ui-common/src/javafx/scene/layout/FlowPane.java	Wed Aug 22 18:59:34 2012 -0400
+++ b/javafx-ui-common/src/javafx/scene/layout/FlowPane.java	Tue Aug 28 10:19:58 2012 +0200
@@ -150,6 +150,8 @@
  */
 public class FlowPane extends Pane {
 
+    private static final double EPSILON = 1e-12;
+
     /********************************************************************
      *  BEGIN static methods
      ********************************************************************/
@@ -572,92 +574,84 @@
     private List<Run> runs = null;
     private double lastMaxRunLength = -1;
     boolean computingRuns = false;
+    
+    private void finishRun(Run run, double runOffset, double runLength, boolean horizontal, double currentHGap, double currentVGap, VPos vPos) {
+        run.runPos = runOffset;
+        if (horizontal) {
+            run.width = runLength - currentHGap;
+            if (vPos != VPos.BASELINE) {
+                run.baselineOffset = run.height;
+            }
+        } else {
+            run.height = runLength - currentVGap;
+            run.baselineOffset = run.height;
+        }
+        runs.add(run);
+    }
+    
+    private List<Run> getRuns(double maxRunLength) {
+        if (runs == null || Math.abs(maxRunLength - lastMaxRunLength) > EPSILON) {
+            try {
+                computingRuns = true;
+                lastMaxRunLength = maxRunLength;
+                runs = new ArrayList();
+                final boolean horizontal = getOrientation() == HORIZONTAL;
+                final VPos vPos = getRowValignment();
+                final double currentVGap = snapSpace(this.getVgap());
+                final double currentHGap = snapSpace(this.getHgap());
+                int index = 0;
+                Run run = new Run(index);
+                double runLength = 0;
+                double runOffset = 0;
 
-    private List<Run> getRuns(double maxRunLength) {
-        if (runs == null || maxRunLength != lastMaxRunLength) {
-            computingRuns = true;
-            lastMaxRunLength = maxRunLength;
-            runs = new ArrayList();
-            double runLength = 0;
-            double runOffset = 0;
-            Run run = new Run();
-            double vgap = snapSpace(this.getVgap());
-            double hgap = snapSpace(this.getHgap());
-
-            final List<Node> children = getChildren();
-            for (int i=0, size=children.size(); i<size; i++) {
-                Node child = children.get(i);
-                if (child.isManaged()) {
-                    LayoutRect nodeRect = new LayoutRect();
-                    nodeRect.node = child;
-                    Insets margin = getMargin(child);
-                    nodeRect.width = computeChildPrefAreaWidth(child, margin);
-                    nodeRect.height = computeChildPrefAreaHeight(child, margin);
-                    double nodeLength = getOrientation() == HORIZONTAL ? nodeRect.width : nodeRect.height;
-                    if (runLength + nodeLength > maxRunLength && runLength > 0) {
+                final List<Node> managedChildren = getManagedChildren();
+                for (final Node child : managedChildren) {
+                    final Insets margin = getMargin(child);
+                    final double width = computeChildPrefAreaWidth(child, margin);
+                    final double height = computeChildPrefAreaHeight(child, margin);
+                    final double alignedHeight = (horizontal && vPos == VPos.BASELINE)? computeChildPrefAreaHeight(child, margin, vPos) : height;
+                    final double nodeSize = horizontal? width : height;
+                    if (runLength + nodeSize > maxRunLength && runLength > 0) {
                         // wrap to next run *unless* its the only node in the run
-                        normalizeRun(run, runOffset);
-                        if (getOrientation() == HORIZONTAL) {
-                            // horizontal
-                            runOffset += run.height + vgap;
-                        } else {
-                            // vertical
-                            runOffset += run.width + hgap;
+                        finishRun(run, runOffset, runLength, horizontal, currentHGap, currentVGap, vPos);
+                        runOffset += horizontal? run.height + currentVGap : run.width + currentHGap;
+                        runLength = 0;
+                        run = new Run(index);
+                    }
+                    run.nodeData.add(runLength);
+                    run.nodeData.add(nodeSize);
+                    if (horizontal) {
+                        runLength += width + currentHGap;
+                        run.height = Math.max(run.height, alignedHeight);
+                        if (vPos == VPos.BASELINE) {
+                            run.baselineOffset = Math.max(run.baselineOffset, (margin != null? margin.getTop() : 0)  + child.getBaselineOffset());
                         }
-                        runs.add(run);
-                        runLength = 0;
-                        run = new Run();
+                    } else {
+                        runLength += height + currentVGap;
+                        run.width = Math.max(run.width, width);
                     }
-                    if (getOrientation() == HORIZONTAL) {
-                        // horizontal
-                        nodeRect.x = runLength;
-                        runLength += nodeRect.width + hgap;
-                    } else {
-                        // vertical
-                        nodeRect.y = runLength;
-                        runLength += nodeRect.height + vgap;
-                    }
-                    run.rects.add(nodeRect);
+                    index++; 
                 }
-
+                // insert last run
+                finishRun(run, runOffset, runLength, horizontal, currentHGap, currentVGap, vPos);
+            } finally {
+                computingRuns = false;
             }
-            // insert last run
-            normalizeRun(run, runOffset);
-            runs.add(run);
-            computingRuns = false;
         }
         return runs;
     }
 
-    private void normalizeRun(Run run, double runOffset) {
-        if (getOrientation() == HORIZONTAL) {
-            // horizontal
-            ArrayList<Node> rownodes = new ArrayList();
-            run.width = (run.rects.size()-1)*snapSpace(getHgap());
-            Insets margins[] = new Insets[run.rects.size()];
-            for (int i=0, max=run.rects.size(); i<max; i++) {
-                LayoutRect lrect = run.rects.get(i);
-                margins[i] = getMargin(lrect.node);
-                rownodes.add(lrect.node);
-                run.width += lrect.width;
-                lrect.y = runOffset;
-            }
-            run.height = computeMaxPrefAreaHeight(rownodes, margins, getRowValignment());
-            run.baselineOffset = getRowValignment() == VPos.BASELINE? getMaxAreaBaselineOffset(rownodes, margins) : run.height;
-
+    // MH: Move to Region once Richard pushed his changes
+    double computeChildPrefAreaHeight(Node child, Insets margin, VPos valignment) {
+        if (valignment == VPos.BASELINE) {
+            final double baseline = child.getBaselineOffset();
+            final double top = margin != null? snapSpace(margin.getTop()) : 0;
+            final double bottom = margin != null? snapSpace(margin.getBottom()) : 0;
+            final double above = baseline + top;
+            final double below = snapSpace(snapSize(child.prefHeight(-1)) - baseline + bottom);
+            return above + below;
         } else {
-            // vertical
-            run.height = (run.rects.size()-1)*snapSpace(getVgap());
-            double maxw = 0;
-            for (int i=0, max=run.rects.size(); i<max; i++) {
-                LayoutRect lrect = run.rects.get(i);
-                run.height += lrect.height;
-                lrect.x = runOffset;
-                maxw = Math.max(maxw, lrect.width);
-            }
-
-            run.width = maxw;
-            run.baselineOffset = run.height;
+            return computeChildPrefAreaHeight(child, margin);
         }
     }
 
@@ -699,31 +693,42 @@
         final double right = insets.getRight();
         final double insideWidth = width - left - right;
         final double insideHeight = height - top - bottom;
+        final List<Node> managedChildren = getManagedChildren();
+        final boolean horizontal = getOrientation() == HORIZONTAL;
+        final Pos currentAlignment = getAlignment();
+        final HPos hPos = currentAlignment.getHpos();
+        final VPos vPos = currentAlignment.getVpos();
+        final VPos rowAlignment = getRowValignment();
 
         //REMIND(aim): need to figure out how to cache the runs to avoid over-calculation
-        final List<Run> runs = getRuns(getOrientation() == HORIZONTAL ? insideWidth : insideHeight);
+        final List<Run> runs = getRuns(horizontal? insideWidth : insideHeight);
+        final double contentSize = horizontal? computeContentHeight(runs) : computeContentWidth(runs);
 
         // Now that the nodes are broken into runs, figure out alignments
         for (int i=0, max=runs.size(); i<max; i++) {
             final Run run = runs.get(i);
+            final int n = run.nodeData.size() / 2;
             final double xoffset = left + computeXOffset(insideWidth,
-                                     getOrientation() == HORIZONTAL ? run.width : computeContentWidth(runs),
-                                     getAlignment().getHpos());
+                                     horizontal? run.width : contentSize,
+                                     hPos);
             final double yoffset = top + computeYOffset(insideHeight,
-                                    getOrientation() == VERTICAL ? run.height : computeContentHeight(runs),
-                                    getAlignment().getVpos());
-            for (int j = 0; j < run.rects.size(); j++) {
-                final LayoutRect lrect = run.rects.get(j);
+                                    !horizontal ? run.height : contentSize,
+                                    vPos);
+            for (int j = 0; j < n; j++) {
 //              System.out.println("flowpane.layout: run="+i+" "+run.width+"x"+run.height+" xoffset="+xoffset+" yoffset="+yoffset+" lrect="+lrect);
-                final double x = xoffset + lrect.x;
-                final double y = yoffset + lrect.y;
-                layoutInArea(lrect.node, x, y,
-                           getOrientation() == HORIZONTAL? lrect.width : run.width,
-                           getOrientation() == VERTICAL? lrect.height : run.height,
-                           run.baselineOffset, getMargin(lrect.node),
+                final int index = 2*j;
+                final double pos = run.nodeData.get(index);
+                final double size = run.nodeData.get(index+1);
+                final double x = xoffset + (horizontal? pos : run.runPos);
+                final double y = yoffset + (horizontal? run.runPos : pos);
+                final Node node = managedChildren.get(run.index + j);
+                layoutInArea(node, x, y,
+                           horizontal? size : run.width,
+                           horizontal? run.height : size,
+                           run.baselineOffset, getMargin(node),
                            // only fill height if we don't have baseline alignment
-                           true, getOrientation() == VERTICAL || getRowValignment() != VPos.BASELINE,
-                           getColumnHalignment(), getRowValignment());
+                           true, !horizontal || rowAlignment != VPos.BASELINE,
+                           getColumnHalignment(), rowAlignment);
             }
         }
     }
@@ -883,23 +888,16 @@
         return impl_CSS_STYLEABLES();
     }
 
-    //REMIND(aim); replace when we get mutable rects
-    private static class LayoutRect {
-        public Node node;
-        double x;
-        double y;
+    private static class Run {
+        final ArrayList<Double> nodeData = new ArrayList();
+        final int index;
+        double runPos;
         double width;
         double height;
-
-        @Override public String toString() {
-            return "LayoutRect node id="+node.getId()+" "+x+","+y+" "+width+"x"+height;
+        double baselineOffset;
+        Run(int index) {
+            this.index = index;
         }
     }
 
-    private static class Run {
-        ArrayList<LayoutRect> rects = new ArrayList();
-        double width;
-        double height;
-        double baselineOffset;
-    }
 }
