From 3dd52c8ccedf9f1a38f27420ea6a001087cc0e5b Mon Sep 17 00:00:00 2001 From: stepan <stepan.sindelar@oracle.com> Date: Fri, 17 Mar 2017 17:56:25 +0100 Subject: [PATCH] FastR Grid: more view-port features implemented --- .../r/library/fastrGrid/DoSetViewPort.java | 67 ++++++++------ .../truffle/r/library/fastrGrid/GPar.java | 6 +- .../r/library/fastrGrid/GridLinesNode.java | 6 +- .../r/library/fastrGrid/GridTextNode.java | 7 +- .../truffle/r/library/fastrGrid/LCircle.java | 6 +- .../truffle/r/library/fastrGrid/LConvert.java | 6 +- .../truffle/r/library/fastrGrid/LPoints.java | 7 +- .../truffle/r/library/fastrGrid/LRect.java | 6 +- .../r/library/fastrGrid/LSegments.java | 6 +- .../r/library/fastrGrid/LUnsetViewPort.java | 88 +++++++++++++++++++ .../truffle/r/library/fastrGrid/Unit.java | 9 +- .../truffle/r/library/fastrGrid/ViewPort.java | 19 ++++ .../r/library/fastrGrid/ViewPortContext.java | 35 ++++---- .../r/library/fastrGrid/ViewPortLocation.java | 48 +++++----- .../library/fastrGrid/ViewPortTransform.java | 20 ++++- .../library/fastrGrid/device/GridDevice.java | 2 +- .../fastrGrid/device/JFrameDevice.java | 18 +--- .../truffle/r/library/fastrGrid/fastrGrid.R | 16 +++- .../foreign/CallAndExternalFunctions.java | 3 + mx.fastr/copyrights/overrides | 1 + 20 files changed, 247 insertions(+), 129 deletions(-) create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java 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 ec20b0d423..f15ca369fd 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 33d7761a60..322ce43195 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 695175e7c2..24cb71abc5 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 13e52dfc66..2c6dc5a516 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 c5262bd3ff..4fc29b79f7 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 3703c83baa..96792070cc 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 67604044ec..0c457f1bed 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 e79c9dcd67..062d23c46d 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 426234d0fb..33e8f7d514 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 0000000000..153358e5ef --- /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 a9dd76013c..fb8112cb3e 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 7bf24ec0aa..99fdd428d3 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 e07043ce1c..0eb93b84f9 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 894d8d90e1..2ea1a4d776 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 cc7656af20..0e8ea8aa08 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 1f0a0d8f03..9e37a873bb 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 758ae81683..8fea72124b 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 84f733bb59..30a16598ea 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 ba396e0f39..cbb9714312 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 0095ec54be..7c18b674af 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 -- GitLab