diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index ec20b0d423e149c5f6586dab80eeee192e20bdad..f15ca369fdb82284828031028df98891189d1eda 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -12,12 +12,14 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.flatten;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.fromFlat;
-import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.identity;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.rotation;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
@@ -26,8 +28,6 @@ import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortLocation.VPLocationFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -50,8 +50,6 @@ class DoSetViewPort extends RBaseNode {
     @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
     @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
     @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
-    @Child private VPLocationFromVPNode vpLocationFromVP = new VPLocationFromVPNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
     @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
 
     public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
@@ -66,7 +64,10 @@ class DoSetViewPort extends RBaseNode {
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
         DrawingContext deviceDrawingContext = GridState.getInitialGPar(currentDevice);
-        calcViewportTransform(pushedViewPort, pushedViewPort.getDataAt(ViewPort.PVP_PARENT), !hasParent, currentDevice, deviceDrawingContext);
+
+        RList parent = asListOrNull(pushedViewPort.getDataAt(ViewPort.PVP_PARENT));
+        boolean doNotRecalculateParent = hasParent && !ViewPort.updateDeviceSizeInVP(parent, currentDevice);
+        calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, deviceDrawingContext);
 
         // TODO: clipping
         pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
@@ -75,18 +76,32 @@ class DoSetViewPort extends RBaseNode {
         return pushedViewPort;
     }
 
-    private void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
+    /**
+     * Calculates and sets the view-port width and height in inches, and transformation matrix and
+     * rotation angle.
+     *
+     * @param viewPort The view-port to be updated.
+     * @param parent The parent of the view-port, null if the view-port is top level.
+     * @param incremental If {@code true} it is assumed that we can just take the transformation
+     *            matrix and other values from the parent without re-calculating them recursively.
+     * @param device This method needs the device in order to convert units
+     * @param deviceDrawingContext This method needs to know the device default drawing context in
+     *            order to convert units for the top level view port
+     */
+    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
         Size parentSize;
         DrawingContext drawingContext;
+        double parentAngle;
         if (parent == null || parent == RNull.instance) {
             parentTransform = TransformMatrix.identity();
             parentContext = ViewPortContext.createDefault();
             parentSize = new Size(device.getWidth(), device.getHeight());
-            vpl = vpLocationFromVP.execute(viewPort);
+            vpl = ViewPortLocation.fromViewPort(viewPort);
             drawingContext = deviceDrawingContext;
+            parentAngle = 0;
         } else {
             assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list";
             RList parentVPList = (RList) parent;
@@ -96,12 +111,13 @@ class DoSetViewPort extends RBaseNode {
             }
             parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
             parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
-            parentContext = vpContextFromVP.execute(parentVPList);
+            parentContext = ViewPortContext.fromViewPort(parentVPList);
+            parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]);
 
             drawingContext = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
             boolean noLayout = (isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSROW)) && isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSCOL))) || isNull(parentData[ViewPort.VP_LAYOUT]);
             if (noLayout) {
-                vpl = vpLocationFromVP.execute(viewPort);
+                vpl = ViewPortLocation.fromViewPort(viewPort);
             } else {
                 vpl = calcViewportLocationFromLayout(getLayoutPos(viewPort, parentVPList), parentVPList, parentSize);
             }
@@ -122,11 +138,10 @@ class DoSetViewPort extends RBaseNode {
 
         // Produce transform for this viewport
         double[][] thisLocation = translation(xInches, yInches);
-        double[][] thisRotation = identity();
-        // TODO: if (viewportAngle(vp) != 0) rotation(viewportAngle(vp), thisRotation);
-
         double[][] thisJustification = translation(xadj, yadj);
         // Position relative to origin of rotation THEN rotate.
+        double viewPortAngle = asDouble(viewPort.getDataAt(ViewPort.VP_ANGLE));
+        double[][] thisRotation = rotation(viewPortAngle);
         double[][] tempTransform = multiply(thisJustification, thisRotation);
         // Translate to bottom-left corner.
         double[][] thisTransform = multiply(tempTransform, thisLocation);
@@ -134,12 +149,11 @@ class DoSetViewPort extends RBaseNode {
         double[][] transform = multiply(thisTransform, parentTransform);
 
         // Sum up the rotation angles
-        // TODO: rotationAngle = parentAngle + viewportAngle(vp);
-        double rotationAngle = 0;
+        double rotationAngle = parentAngle + viewPortAngle;
 
         // Finally, allocate the rows and columns for this viewport's layout if it has one
         if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) {
-            ViewPortContext vpCtx = vpContextFromVP.execute(viewPort);
+            ViewPortContext vpCtx = ViewPortContext.fromViewPort(viewPort);
             DrawingContext drawingCtx = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)));
             calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, drawingCtx);
         }
@@ -178,8 +192,8 @@ class DoSetViewPort extends RBaseNode {
         int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT));
         int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying();
         if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) {
-            double sumRelWidth = sumRelativeDimension(layoutSize, layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
-            double sumRelHeight = sumRelativeDimension(layoutSize, layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
+            double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
+            double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
             double tempWidth = reducedWidth;
             double tempHeight = reducedHeight;
             double denom;
@@ -244,17 +258,18 @@ class DoSetViewPort extends RBaseNode {
 
     private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
                     GridDevice device, DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
+        assert relativeItems.length == npcItems.length;
         UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
         double totalUnrespectedSize = 0;
         if (reducedDim > 0) {
-            for (int i = 0; i < layoutSize.ncol; i++) {
+            for (int i = 0; i < relativeItems.length; i++) {
                 if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
                     totalUnrespectedSize += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
                 }
             }
         }
         // set the remaining width/height to zero or to proportion of totalUnrespectedSize
-        for (int i = 0; i < layoutSize.ncol; i++) {
+        for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
                 npcItems[i] = 0;
                 if (totalUnrespectedSize > 0) {
@@ -265,8 +280,8 @@ class DoSetViewPort extends RBaseNode {
         }
     }
 
-    private boolean rowColRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
-        return isColumn ? colRespected(respected, respected, layoutRespectMat, layoutSize) : rowRespected(respected, row, layoutRespectMat, layoutSize);
+    private boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
+        return isColumn ? colRespected(respected, rowOrCol, layoutRespectMat, layoutSize) : rowRespected(respected, rowOrCol, layoutRespectMat, layoutSize);
     }
 
     private boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
@@ -293,11 +308,11 @@ class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(LayoutSize layoutSize, RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
+    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
                     boolean isWidth) {
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 0, 1);
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
         double totalWidth = 0;
-        for (int i = 0; i < layoutSize.ncol; i++) {
+        for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i]) {
                 totalWidth += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
             }
@@ -349,7 +364,7 @@ class DoSetViewPort extends RBaseNode {
         double totalHeight = sum(heights, 0, pos.layoutSize.nrow);
         double width = sum(widths, pos.colMin, pos.colMax - pos.colMin + 1);
         double height = sum(heights, pos.rowMin, pos.rowMax - pos.rowMin + 1);
-        double left = parentSize.getWidth() * pos.layoutSize.hjust - totalWidth * pos.layoutSize.hjust + sum(widths, 0, pos.colMin - 1);
+        double left = parentSize.getWidth() * pos.layoutSize.hjust - totalWidth * pos.layoutSize.hjust + sum(widths, 0, pos.colMin);
         double bottom = parentSize.getHeight() * pos.layoutSize.vjust + (1 - pos.layoutSize.vjust) * totalHeight - sum(heights, 0, pos.rowMax + 1);
         ViewPortLocation result = new ViewPortLocation();
         result.width = newUnit(width, Unit.INCHES);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 33d7761a60278e2b3384a02ef42d71aa10b3c37f..322ce4319582e00961dd7e97be7bc8945288c694 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -82,14 +82,14 @@ public final class GPar {
     public static RList createNew() {
         Object[] data = new Object[GP_LENGTH];
         Arrays.fill(data, RNull.instance);
-        data[GP_FILL] = "grey";
+        data[GP_FILL] = "transparent";
         data[GP_COL] = "black";
         data[GP_GAMMA] = newDoubleVec(0);
         data[GP_LTY] = "solid"; // TODO: LineType enum...
         data[GP_LWD] = newDoubleVec(1);
         data[GP_CEX] = newDoubleVec(1);
-        data[GP_FONTSIZE] = newDoubleVec(12);
-        data[GP_LINEHEIGHT] = newDoubleVec(1.0);
+        data[GP_FONTSIZE] = newDoubleVec(16);
+        data[GP_LINEHEIGHT] = newDoubleVec(1.2);
         data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);  // TODO: font constants?
         data[GP_FONTFAMILY] = ""; // means default font (probably)
         data[GP_ALPHA] = newDoubleVec(1);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 695175e7c26b926c6ce2c47c78c524cd69208b63..24cb71abc5bd43d09fa64d4c97790293c3a0119f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -43,7 +42,6 @@ public abstract class GridLinesNode extends Node {
 
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     void execute(RAbstractVector x, RAbstractVector y, RList lengths) {
         GridContext ctx = GridContext.getContext();
@@ -51,8 +49,8 @@ public abstract class GridLinesNode extends Node {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         // Convert the list of vectors of indexes to type-safe array and calculate the max length of
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 13e52dfc66885702da15fcee914f19de9291ce4c..2c6dc5a5165ffc6b52859283145d29b3d38176e4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -34,7 +34,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -58,7 +57,7 @@ public final class GridTextNode extends RBaseNode {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
     private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile();
     private final boolean draw;
 
@@ -95,8 +94,8 @@ public final class GridTextNode extends RBaseNode {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, x, y);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index c5262bd3ff8b07d7bf2db368fb117cd930dcad56..4fc29b79f7e51f06e1ff1415dc38cd7bc3ee0093 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -29,7 +28,6 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LCircle.class);
@@ -49,8 +47,8 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 3703c83baa9d98587184cef5cc43f1dae7d81b64..96792070cc85a0ce07d5eddd927e0925e4e7a5e5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -21,7 +21,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -36,7 +35,6 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LConvert.class);
@@ -58,8 +56,8 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = unitLength.execute(units);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 67604044ec4ba6305f9429280680d2daf7e8d8ed..0c457f1bed8c0c315a1c9fd7fcf6d91d8e7a2095 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -18,7 +18,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
@@ -41,7 +40,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
 
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
     @Child private UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
 
@@ -66,8 +65,8 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         RList gpar = ctx.getGridState().getGpar();
         DrawingContext drawingCtx = GPar.asDrawingContext(gpar);
         double cex = GPar.getCex(gpar);
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         // Note: unlike in other drawing primitives, we only consider length of x
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index e79c9dcd67cd90dba367f726de114c2dfb310ad3..062d23c46da42c9de0316b2e656743b2b85028fc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -31,7 +30,6 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LRect.class);
@@ -54,8 +52,8 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 426234d0fbf5b1a9ae978f84f4d4ffc45a3731ad..33e8f7d514746ddb8cd051186cf3c7fe9b06a146 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -32,7 +31,6 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LSegments.class);
@@ -53,8 +51,8 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
new file mode 100644
index 0000000000000000000000000000000000000000..153358e5ef124e85dd421c6589fd1ce03f185e21
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -0,0 +1,88 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
+
+public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
+    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
+
+    static {
+        Casts casts = new Casts(LUnsetViewPort.class);
+        casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst();
+    }
+
+    public static LUnsetViewPort create() {
+        return LUnsetViewPortNodeGen.create();
+    }
+
+    @Specialization
+    Object unsetViewPort(int n) {
+        GridContext ctx = GridContext.getContext();
+        GridState gridState = ctx.getGridState();
+
+        // go n-steps up the view-port tree
+        RList gvp = gridState.getViewPort();
+        RList newVp = gvp;
+        for (int i = 0; i < n; i++) {
+            gvp = newVp;
+            newVp = asListOrNull(gvp.getDataAt(ViewPort.PVP_PARENT));
+            if (newVp == null) {
+                throw error(Message.GENERIC, "cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)");
+            }
+        }
+
+        // gvp will be removed, newVp will be the new view-port
+        // first update children of newVp -> remove gvp
+        REnvironment children = (REnvironment) newVp.getDataAt(ViewPort.PVP_CHILDREN);
+        String gvpName = RRuntime.asString(gvp.getDataAt(ViewPort.VP_NAME));
+        safeRemoveFromEnv(children, gvpName);
+
+        // update newVp transform etc. because it will be the current vp, it has to be up to date
+        GridDevice device = ctx.getCurrentDevice();
+        if (ViewPort.updateDeviceSizeInVP(newVp, device)) {
+            // Note: like in other places calling this, why incremental == true, given that the
+            // device has changed? Don't we want to recalculate the whole tree?
+            doSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
+        }
+
+        gridState.setGpar(asList(newVp.getDataAt(ViewPort.PVP_GPAR)));
+
+        // TODO: clipping
+        gridState.setViewPort(newVp);
+
+        // remove the parent link from the old viewport
+        gvp.setDataAt(gvp.getInternalStore(), ViewPort.PVP_PARENT, null);
+        return RNull.instance;
+    }
+
+    private void safeRemoveFromEnv(REnvironment children, String gvpName) {
+        try {
+            children.rm(gvpName);
+        } catch (PutException e) {
+            throw RInternalError.shouldNotReachHere("Cannot update view-port children environment");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index a9dd76013ca467a1189d3bcefbdad1c519d3c010..fb8112cb3e770b86a14e30282b7117535f135740 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitLengthNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -586,7 +585,7 @@ public class Unit {
         @Child private RGridCodeCall getUnitXY = new RGridCodeCall("grobConversionGetUnitXY");
         @Child private RGridCodeCall postDrawCode = new RGridCodeCall("grobConversionPostDraw");
         @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-        @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
         @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
         @Child private UnitToInchesNode unitToInchesNode;
 
@@ -595,7 +594,7 @@ public class Unit {
         public double execute(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
             GridContext ctx = GridContext.getContext();
             RList currentVP = ctx.getGridState().getViewPort();
-            getViewPortTransform.execute(currentVP);
+            getViewPortTransform.execute(currentVP, conversionCtx.device);
 
             RList savedGPar = ctx.getGridState().getGpar();
             Object savedGrob = ctx.getGridState().getCurrentGrob();
@@ -609,8 +608,8 @@ public class Unit {
              */
             currentVP = ctx.getGridState().getViewPort();
             RList currentGP = ctx.getGridState().getGpar();
-            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-            ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, conversionCtx.device);
+            ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
 
             // getUnitXY returns a list with either one or two items
             RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId}, ArgumentsSignature.empty(2)));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 7bf24ec0aa438ecc35995528cfdfdfb5660c0093..99fdd428d3e57bfff7a6cff318801655d1b3fdb2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -11,7 +11,9 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.inchesToCm;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
@@ -80,6 +82,23 @@ class ViewPort {
     public static final int LAYOUT_JUST = 7;
     private static final int LAYOUT_VJUST = 8;
 
+    /**
+     * Updates the device size in the viewport and returns {@code true} if the size has changed.
+     */
+    public static boolean updateDeviceSizeInVP(RList viewPort, GridDevice device) {
+        double devWidthCm = inchesToCm(device.getWidth());
+        boolean result = false;
+        if (Math.abs(devWidthCm - asDouble(viewPort.getDataAt(PVP_DEVWIDTHCM))) >= 1e-6) {
+            viewPort.setDataAt(viewPort.getInternalStore(), PVP_DEVWIDTHCM, devWidthCm);
+            result = true;
+        }
+        double devHeightCm = inchesToCm(device.getHeight());
+        if (Math.abs(devHeightCm - asDouble(viewPort.getDataAt(PVP_DEVHEIGHTCM))) >= 1e-6) {
+            viewPort.setDataAt(viewPort.getInternalStore(), PVP_DEVHEIGHTCM, devHeightCm);
+        }
+        return result;
+    }
+
     /**
      * Represents the integer values extracted from {@link #LAYOUT_NCOL} and {@link #LAYOUT_NROW}.
      * In the R world, RNulls are valid values for those, we convert them to -1 to keep type safety.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
index e07043ce1c1a3e4e94be522d83d5eff8794e0406..0eb93b84f92ae34ba54ddf944a0e867bb9bfde62 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
@@ -11,11 +11,10 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector;
 
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
-import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
@@ -37,22 +36,20 @@ public final class ViewPortContext {
         return result;
     }
 
-    public static final class VPContextFromVPNode extends Node {
-        @Child private CastNode castVector = newCastBuilder().asDoubleVector().mustBe(Predef.size(2)).buildCastNode();
-
-        public ViewPortContext execute(RList viewPort) {
-            ViewPortContext result = new ViewPortContext();
-            RAbstractDoubleVector x = castVec(viewPort.getDataAt(ViewPort.VP_XSCALE));
-            result.xscalemin = x.getDataAt(0);
-            result.xscalemax = x.getDataAt(1);
-            RAbstractDoubleVector y = castVec(viewPort.getDataAt(ViewPort.VP_YSCALE));
-            result.yscalemin = y.getDataAt(0);
-            result.yscalemax = y.getDataAt(1);
-            return result;
+    public static ViewPortContext fromViewPort(RList viewPort) {
+        ViewPortContext result = new ViewPortContext();
+        RAbstractDoubleVector x = asDoubleVector(viewPort.getDataAt(ViewPort.VP_XSCALE));
+        if (x.getLength() != 2) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "view-port xscale must be vector of size 2");
         }
-
-        private RAbstractDoubleVector castVec(Object val) {
-            return (RAbstractDoubleVector) castVector.execute(val);
+        result.xscalemin = x.getDataAt(0);
+        result.xscalemax = x.getDataAt(1);
+        RAbstractDoubleVector y = asDoubleVector(viewPort.getDataAt(ViewPort.VP_YSCALE));
+        if (y.getLength() != 2) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "view-port yscale must be vector of size 2");
         }
+        result.yscalemin = y.getDataAt(0);
+        result.yscalemax = y.getDataAt(1);
+        return result;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
index 894d8d90e134561eb12bf81bfbeb81156eed468b..2ea1a4d776efaa252721e8bcf1c58f6f81e81103 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
@@ -11,13 +11,13 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector;
 
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 /**
@@ -25,31 +25,25 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
  * for them. However, the unit object should contain only single value.
  */
 public class ViewPortLocation {
-    public RAbstractDoubleVector x;
-    public RAbstractDoubleVector y;
-    public RAbstractDoubleVector width;
-    public RAbstractDoubleVector height;
+    public RAbstractContainer x;
+    public RAbstractContainer y;
+    public RAbstractContainer width;
+    public RAbstractContainer height;
     public double hjust;
     public double vjust;
 
-    public static final class VPLocationFromVPNode extends Node {
-        @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
-        @Child private CastNode castJustVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().mustBe(size(2)).buildCastNode();
-
-        public ViewPortLocation execute(RList viewPort) {
-            ViewPortLocation r = new ViewPortLocation();
-            r.x = vec(viewPort.getDataAt(ViewPort.VP_X));
-            r.y = vec(viewPort.getDataAt(ViewPort.VP_Y));
-            r.width = vec(viewPort.getDataAt(ViewPort.VP_WIDTH));
-            r.height = vec(viewPort.getDataAt(ViewPort.VP_HEIGHT));
-            RAbstractDoubleVector just = (RAbstractDoubleVector) castJustVector.execute(viewPort.getDataAt(ViewPort.VP_VALIDJUST));
-            r.hjust = just.getDataAt(0);
-            r.vjust = just.getDataAt(1);
-            return r;
-        }
-
-        private RAbstractDoubleVector vec(Object val) {
-            return (RAbstractDoubleVector) castDoubleVector.execute(val);
+    public static ViewPortLocation fromViewPort(RList viewPort) {
+        ViewPortLocation r = new ViewPortLocation();
+        r.x = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_X));
+        r.y = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_Y));
+        r.width = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_WIDTH));
+        r.height = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_HEIGHT));
+        RAbstractDoubleVector just = asDoubleVector(viewPort.getDataAt(ViewPort.VP_VALIDJUST));
+        if (just.getLength() != 2) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected size of layout justification vector.");
         }
+        r.hjust = just.getDataAt(0);
+        r.vjust = just.getDataAt(1);
+        return r;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
index cc7656af20cab527df0c59e18e903c80ccf2d702..0e8ea8aa082fd627a3857caa998e923d758989fc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -14,7 +14,9 @@ package com.oracle.truffle.r.library.fastrGrid;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -36,10 +38,15 @@ public final class ViewPortTransform {
     public static final class GetViewPortTransformNode extends Node {
         @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
         @Child private CastNode castScalarDouble = newCastBuilder().mustBe(numericValue()).asDoubleVector().findFirst().buildCastNode();
+        @Child private DoSetViewPort doSetViewPort;
 
-        public ViewPortTransform execute(RList viewPort) {
-            // TODO: if device has changed, recalculate the VP transform!!! Some code, e.g.
-            // GrobUnitToInches relies on that
+        public ViewPortTransform execute(RList viewPort, GridDevice device) {
+            if (ViewPort.updateDeviceSizeInVP(viewPort, device)) {
+                // Note: GnuR sets incremental parameter to true, but don't we need to recalculate
+                // the parent(s) as well?
+                initDoSetViewportNode();
+                doSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
+            }
             double width = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
             double height = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
             double rotationAngle = getScalar(viewPort.getDataAt(ViewPort.VP_ANGLE));
@@ -48,6 +55,13 @@ public final class ViewPortTransform {
             return new ViewPortTransform(width, height, rotationAngle, transform);
         }
 
+        private void initDoSetViewportNode() {
+            if (doSetViewPort == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                doSetViewPort = new DoSetViewPort();
+            }
+        }
+
         private double getScalar(Object value) {
             return (double) castScalarDouble.execute(value);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 1f0a0d8f039be4c15d60129bb1229fa216d39ee3..9e37a873bb46214d7035d2fefb13467cd7df174e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -31,7 +31,7 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 public interface GridDevice {
     void openNewPage();
 
-    void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width);
+    void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height);
 
     /**
      * Connects given points with a line, there has to be at least two points in order to actually
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 758ae81683b6e821c907916efb8cec8dbc4b85db..8fea72124b5d8679a8dfa8e466bc8e42b006ddad 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -36,8 +36,6 @@ import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
 import java.util.function.Supplier;
 
-import javax.swing.UIManager;
-
 import com.oracle.truffle.r.library.graphics.FastRFrame;
 
 public class JFrameDevice implements GridDevice {
@@ -71,9 +69,9 @@ public class JFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width) {
+    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height) {
         setContext(ctx);
-        drawShape(ctx, new Rectangle2D.Double(leftX, topY, heigh, width));
+        drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height));
     }
 
     @Override
@@ -139,14 +137,6 @@ public class JFrameDevice implements GridDevice {
         });
     }
 
-    @Override
-    public void initDrawingContext(DrawingContext ctx) {
-        Color color = UIManager.getColor("Panel.background");
-        if (color != null) {
-            ctx.setFillColor(toGridColor(color));
-        }
-    }
-
     private void drawShape(DrawingContext drawingCtx, Shape shape) {
         Paint paint = graphics.getPaint();
         graphics.setPaint(fromGridColor(drawingCtx.getFillColor()));
@@ -175,8 +165,4 @@ public class JFrameDevice implements GridDevice {
     private static Color fromGridColor(GridColor color) {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
-
-    private static GridColor toGridColor(Color color) {
-        return new GridColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index 84f733bb595008116a11178d66b6893bcbe94ede..30a16598eaf5a19953b64fe03b5bf148e992072b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -45,6 +45,19 @@ L_setviewport <- function(vp, hasParent) {
     .Internal(.fastr.grid.doSetViewPort(pushedVP, hasParent, TRUE));
 }
 
+L_unsetviewport <- function(n) {
+    gvp <- .Call(grid:::L_currentViewport)
+    newVp <- gvp;
+    for (i in 1:n) {
+        gvp <- newVp;
+        newVp <- gvp$parent;
+        if (is.null(newVp)) {
+            error("cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)")
+        }
+    }
+    # remove
+}
+
 ###################################################
 # Helper functions to deal with null and grob units
 # these functions are invoked from Java directly
@@ -80,7 +93,8 @@ isPureNullUnit <- function(unit, index) {
     } else if (inherits(unit, "unit.list")) {
         return(isPureNullUnit(unit[[indexMod(index, length(unit))]], 1))
     }
-    unitId <- attr(unit, "valid.unit")
+    unitIdVec <- attr(unit, "valid.unit")
+    unitId <- unitIdVec[[indexMod(index, length(unitIdVec))]]
     if (unitId == L_GROBWIDTH) {
         return(isPureNullUnitGrobDim(unit, index, grid:::width))
     } else if (unitId == L_GROBHEIGHT) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index ba396e0f39fc1d68144c2a87f676b6cb71d0cf4b..cbb9714312f98d8d88db8579c8d3e0825cd8f382 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.library.fastrGrid.LRect;
 import com.oracle.truffle.r.library.fastrGrid.LSegments;
 import com.oracle.truffle.r.library.fastrGrid.LText;
 import com.oracle.truffle.r.library.fastrGrid.LTextBounds;
+import com.oracle.truffle.r.library.fastrGrid.LUnsetViewPort;
 import com.oracle.truffle.r.library.fastrGrid.LUpViewPort;
 import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
@@ -694,6 +695,8 @@ public class CallAndExternalFunctions {
                     return LUpViewPort.create();
                 case "L_initViewportStack":
                     return new LInitViewPortStack();
+                case "L_unsetviewport":
+                    return LUnsetViewPort.create();
                 case "L_setviewport":
                 case "L_downviewport":
                     return getExternalFastRGridBuiltinNode(name);
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 0095ec54be32afb7dde5f2cff0b1a5d62c8bf2d8..7c18b674af82fa67a5378855747a905b446ecfca 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -778,6 +778,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.jav
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright