Skip to content
Snippets Groups Projects
Commit cf455106 authored by stepan's avatar stepan
Browse files

FastR grid: implement L_convert

parent a70121df
No related branches found
No related tags found
No related merge requests found
/*
* 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;
}
}
......@@ -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");
}
}
}
}
......@@ -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":
......
......@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment