From cf4551064e7d6a2531e1859a24dd9dbea2cccdbf Mon Sep 17 00:00:00 2001 From: stepan <stepan.sindelar@oracle.com> Date: Tue, 7 Mar 2017 14:16:07 +0100 Subject: [PATCH] FastR grid: implement L_convert --- .../truffle/r/library/fastrGrid/LConvert.java | 98 +++++++++++++++++++ .../truffle/r/library/fastrGrid/Unit.java | 84 ++++++++++++---- .../foreign/CallAndExternalFunctions.java | 3 + mx.fastr/copyrights/overrides | 1 + 4 files changed, 167 insertions(+), 19 deletions(-) create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java 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 new file mode 100644 index 0000000000..0733409cb1 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java @@ -0,0 +1,98 @@ +/* + * 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.Unit.NATIVE; +import static com.oracle.truffle.r.library.fastrGrid.Unit.NPC; +import static com.oracle.truffle.r.library.fastrGrid.Unit.VALID_UNIT_ATTR; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; +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; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +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); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(3))); + casts.arg(2).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(3))); + casts.arg(3).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(Unit.LAST_NORMAL_UNIT))); + } + + public static LConvert create() { + return LConvertNodeGen.create(); + } + + @Specialization + Object doConvert(RAbstractVector units, int axisFrom, int axisTo, int unitTo) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP); + ViewPortContext vpContext = vpContextFromVP.execute(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx); + + int length = unitLength.execute(units); + double[] result = new double[length]; + + int fromUnitId = RRuntime.asInteger(units.getAttr(VALID_UNIT_ATTR)); + boolean relativeUnits = isRelative(unitTo) || isRelative(fromUnitId); + if ((vpTransform.size.getHeight() < 1e-6 || vpTransform.size.getWidth() < 1e-6) && relativeUnits) { + throw RInternalError.unimplemented("L_convert: relative units with close to zero width or height"); + } + + for (int i = 0; i < length; i++) { + double inches; + if (isXAxis(axisFrom)) { + inches = unitToInches.convertX(units, i, conversionCtx); + } else { + inches = unitToInches.convertY(units, i, conversionCtx); + } + if (isXAxis(axisTo)) { + result[i] = Unit.convertFromInches(inches, unitTo, vpTransform.size.getWidth(), vpContext.xscalemin, vpContext.xscalemax, drawingCtx); + } else { + result[i] = Unit.convertFromInches(inches, unitTo, vpTransform.size.getHeight(), vpContext.yscalemin, vpContext.yscalemax, drawingCtx); + } + } + + return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR); + } + + private static boolean isRelative(int unitId) { + return unitId == NPC || unitId == NATIVE; + } + + // what = 0 means x, 1 means y, 2 means width, 3 means height + private static boolean isXAxis(int what) { + return what % 2 == 0; + } +} 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 c12899186e..f646edaf0c 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 @@ -34,13 +34,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; * enter our system. */ public class Unit { - private static final String VALID_UNIT_ATTR = "valid.unit"; + static final String VALID_UNIT_ATTR = "valid.unit"; - private static final int NPC = 0; + public static final int NPC = 0; public static final int CM = 1; public static final int INCHES = 2; - private static final int LINES = 3; - private static final int NATIVE = 4; + public static final int LINES = 3; + public static final int NATIVE = 4; public static final int NULL = 5; /* only used in layout specifications (?) */ public static final int SNPC = 6; public static final int MM = 7; @@ -71,6 +71,7 @@ public class Unit { public static final int GROBHEIGHT = 22; public static final int GROBASCENT = 23; public static final int GROBDESCENT = 24; + public static final int LAST_NORMAL_UNIT = GROBDESCENT; /* * No longer used */ @@ -97,6 +98,65 @@ public class Unit { return UnitToInchesNode.create(); } + static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) { + switch (unitId) { + case NATIVE: + return ((value + scalemin) * (scalemax - scalemin)) / vpSize; + case NPC: + return value / vpSize; + case CM: + return value * CM_IN_INCH; + case MM: + return value * CM_IN_INCH * 10; + case INCHES: + return value; + case POINTS: + return value * INCH_TO_POINTS_FACTOR; + case LINES: + return (value * INCH_TO_POINTS_FACTOR) / (drawingCtx.getFontSize() * drawingCtx.getLineHeight()); + // following units are not supported even by original grid + case SNPC: + case MYCHAR: + case MYLINES: + case STRINGWIDTH: + case MYSTRINGWIDTH: + case STRINGHEIGHT: + case MYSTRINGHEIGHT: + case GROBX: + case GROBY: + case GROBWIDTH: + case GROBHEIGHT: + case NULL: + default: + throw RInternalError.unimplemented("unit type " + unitId + " in convertFromInches"); + } + } + + static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) { + switch (unitId) { + case NATIVE: + return ((value - scalemin) / (scalemax - scalemin)) * vpSize; + case NPC: + return value * vpSize; + case POINTS: + return value / INCH_TO_POINTS_FACTOR; + case CM: + return value / CM_IN_INCH; + case MM: + return value / (CM_IN_INCH * 10); + case LINES: + case MYLINES: + return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR; + + default: + throw RInternalError.unimplemented("unit type " + unitId + " in convertToInches"); + } + } + + public static UnitElementAtNode createElementAtNode() { + return UnitElementAtNode.create(); + } + public abstract static class UnitNodeBase extends Node { @Child private InheritsCheckNode inheritsCheckNode = new InheritsCheckNode("unit.arithmetic"); @@ -191,7 +251,7 @@ public class Unit { @Specialization(guards = "!isArithmetic(value)") double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) { int unitId = (Integer) castUnitId.execute(value.getAttr(VALID_UNIT_ATTR)); - return convert(elementAtNode.execute(value, index % value.getLength()), unitId, vpSize, scalemin, scalemax, drawingCtx); + return convertToInches(elementAtNode.execute(value, index % value.getLength()), unitId, vpSize, scalemin, scalemax, drawingCtx); } @Specialization(guards = "isArithmetic(list)") @@ -199,19 +259,5 @@ public class Unit { throw RInternalError.unimplemented("UnitToInches for arithmetic units"); } - private static double convert(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) { - switch (unitId) { - case NATIVE: - return ((value - scalemin) / (scalemax - scalemin)) * vpSize; - case NPC: - return value * vpSize; - case LINES: - case MYLINES: - return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR; - - default: - throw RInternalError.unimplemented("unit type " + unitId + " in UnitToInches"); - } - } } } 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 9a51634737..9e39ceca94 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 @@ -27,6 +27,7 @@ import com.oracle.truffle.r.library.fastrGrid.GridStateGetNode; import com.oracle.truffle.r.library.fastrGrid.GridStateSetNode; import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal; import com.oracle.truffle.r.library.fastrGrid.LCircle; +import com.oracle.truffle.r.library.fastrGrid.LConvert; import com.oracle.truffle.r.library.fastrGrid.LGridDirty; import com.oracle.truffle.r.library.fastrGrid.LInitGrid; import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack; @@ -680,6 +681,8 @@ public class CallAndExternalFunctions { return LInitGrid.create(); case "L_newpage": return new LNewPage(); + case "L_convert": + return LConvert.create(); // Viewport management case "L_upviewport": diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 670e335899..8119e383c8 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -789,3 +789,4 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNam com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright -- GitLab