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

Remove old FastR java graphics & provide grDevices and graphics simulation layer for FastR grid.

parent ab0e94a1
No related branches found
No related tags found
No related merge requests found
Showing
with 398 additions and 691 deletions
......@@ -23,15 +23,15 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
public class DrawArrowsNode extends Node {
class DrawArrowsNode extends Node {
// Structure of an arrow description
public static final int ARROWANGLE = 0;
public static final int ARROWLENGTH = 1;
public static final int ARROWENDS = 2;
public static final int ARROWTYPE = 3;
private static final int ARROWANGLE = 0;
private static final int ARROWLENGTH = 1;
private static final int ARROWENDS = 2;
private static final int ARROWTYPE = 3;
// known values of ARROWTYPE
public static final int ARROWTYPE_LINES = 1;
public static final int ARROWTYPE_POLYGON = 2;
private static final int ARROWTYPE_LINES = 1;
private static final int ARROWTYPE_POLYGON = 2;
@Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
......
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.r.library.fastrGrid;
import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice;
import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
import com.oracle.truffle.r.runtime.RInternalCode;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull;
/**
* Implements the lookup for externals replaced by the FastR grid package.
*/
public class FastRGridExternalLookup {
public static RExternalBuiltinNode lookupDotExternal(String name) {
switch (name) {
case "devholdflush":
return new IgnoredGridExternal(RNull.instance);
case "PDF":
return new IgnoredGridExternal(RNull.instance);
default:
return null;
}
}
public static RExternalBuiltinNode lookupDotExternal2(String name) {
switch (name) {
case "C_par":
return new CPar();
case "X11":
return new InitWindowedDevice();
default:
return null;
}
}
public static RExternalBuiltinNode lookupDotCall(String name) {
switch (name) {
case "L_gridDirty":
return new LGridDirty();
case "L_initGrid":
return LInitGrid.create();
case "L_newpage":
return new LNewPage();
case "L_convert":
return LConvert.create();
// Viewport management
case "L_upviewport":
return LUpViewPort.create();
case "L_initViewportStack":
return new LInitViewPortStack();
case "L_unsetviewport":
return LUnsetViewPort.create();
case "L_setviewport":
case "L_downviewport":
return getExternalFastRGridBuiltinNode(name);
// Drawing primitives
case "L_rect":
return LRect.create();
case "L_lines":
return LLines.create();
case "L_polygon":
return LPolygon.create();
case "L_text":
return LText.create();
case "L_textBounds":
return LTextBounds.create();
case "L_segments":
return LSegments.create();
case "L_circle":
return LCircle.create();
case "L_points":
return LPoints.create();
// Simple grid state access
case "L_getGPar":
return new GridStateGetNode(GridState::getGpar);
case "L_setGPar":
return GridStateSetNode.create((state, val) -> state.setGpar((RList) val));
case "L_getCurrentGrob":
return new GridStateGetNode(GridState::getCurrentGrob);
case "L_setCurrentGrob":
return GridStateSetNode.create(GridState::setCurrentGrob);
case "L_currentViewport":
return new GridStateGetNode(GridState::getViewPort);
case "L_initGPar":
return new LInitGPar();
// Display list stuff: not implemented atm
case "L_getDisplayList":
return new IgnoredGridExternal(RDataFactory.createList());
case "L_getDLindex":
return new IgnoredGridExternal(0);
case "L_getDLon":
case "L_getEngineDLon":
return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE);
case "L_initDisplayList":
case "L_newpagerecording":
case "L_setDisplayList":
case "L_setDLelt":
case "L_setDLindex":
case "L_setDLon":
return new IgnoredGridExternal(RNull.instance);
// These methods do not use graphics system or any global state. For now,
// we can re-use the native implementation, which in the future should be rewritten
// to managed code.
case "L_validUnits":
return null;
default:
if (name.startsWith("L_")) {
throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
} else {
return null;
}
}
}
private static RExternalBuiltinNode getExternalFastRGridBuiltinNode(String name) {
return new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name);
}
}
......@@ -29,14 +29,14 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
/**
* Gets a specified attribute of current {@link GridState}.
*/
public class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
private final Function<GridState, Object> getter;
static {
Casts.noCasts(GridStateGetNode.class);
}
public GridStateGetNode(Function<GridState, Object> getter) {
GridStateGetNode(Function<GridState, Object> getter) {
this.getter = getter;
}
......
......@@ -29,14 +29,14 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
* A node for externals that we ignore, becuase we do not need to implement them or because they
* support functionallity we do not implement yet, especially record/replay.
*/
public class IgnoredGridExternal extends RExternalBuiltinNode {
class IgnoredGridExternal extends RExternalBuiltinNode {
private final Object result;
static {
Casts.noCasts(IgnoredGridExternal.class);
}
public IgnoredGridExternal(Object result) {
IgnoredGridExternal(Object result) {
this.result = result;
}
......
......@@ -19,7 +19,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RNull;
public class LGridDirty extends RExternalBuiltinNode {
class LGridDirty extends RExternalBuiltinNode {
@Child private InitViewPortNode initViewPort = new InitViewPortNode();
private final ConditionProfile initViewPortProfile = ConditionProfile.createCountingProfile();
......
......@@ -26,7 +26,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RNull;
public class LInitGPar extends RExternalBuiltinNode {
class LInitGPar extends RExternalBuiltinNode {
static {
Casts.noCasts(LInitGPar.class);
}
......
......@@ -18,7 +18,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RNull;
public class LInitViewPortStack extends RExternalBuiltinNode {
class LInitViewPortStack extends RExternalBuiltinNode {
@Child private InitViewPortNode initViewPortNode = new InitViewPortNode();
static {
Casts.noCasts(LInitViewPortStack.class);
......
......@@ -14,7 +14,7 @@ package com.oracle.truffle.r.library.fastrGrid;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.runtime.data.RNull;
public class LNewPage extends RExternalBuiltinNode.Arg0 {
class LNewPage extends RExternalBuiltinNode.Arg0 {
static {
Casts.noCasts(LNewPage.class);
}
......
......@@ -25,19 +25,27 @@ package com.oracle.truffle.r.library.fastrGrid.device;
import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.util.function.Supplier;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineType;
import com.oracle.truffle.r.library.graphics.FastRFrame;
import com.oracle.truffle.r.runtime.RInternalError;
public class JFrameDevice implements GridDevice {
......@@ -214,4 +222,41 @@ public class JFrameDevice implements GridDevice {
twodashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize / 2f, dashSize}, 0f);
longdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{2f * dashSize}, 0f);
}
private static class FastRFrame extends JFrame {
private static final long serialVersionUID = 1L;
private final Dimension framePreferredSize = new Dimension(720, 720);
private final JPanel fastRComponent = new JPanel();
FastRFrame() throws HeadlessException {
super("FastR");
addCloseListener();
createUI();
center();
}
private void createUI() {
setLayout(new BorderLayout());
setSize(framePreferredSize);
add(fastRComponent, BorderLayout.CENTER);
fastRComponent.setPreferredSize(getSize());
}
private void addCloseListener() {
addWindowFocusListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
dispose();
}
});
}
private void center() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = getSize();
int x = (screenSize.width - frameSize.width) / 2;
int y = (screenSize.height - frameSize.height) / 2;
setLocation(x, y);
}
}
}
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -20,56 +20,33 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.r.library.graphics;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class FastRFrame extends JFrame {
private static final long serialVersionUID = 1L;
private final Dimension framePreferredSize = new Dimension(720, 720);
private final FastRComponent fastRComponent = new FastRComponent();
public FastRFrame() throws HeadlessException {
super("FastR");
addCloseListener();
createUI();
center();
}
private void createUI() {
setLayout(new BorderLayout());
setSize(framePreferredSize);
add(fastRComponent, BorderLayout.CENTER);
fastRComponent.setPreferredSize(getSize());
}
private void addCloseListener() {
addWindowFocusListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
dispose();
}
});
}
private void center() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = getSize();
int x = (screenSize.width - frameSize.width) / 2;
int y = (screenSize.height - frameSize.height) / 2;
setLocation(x, y);
package com.oracle.truffle.r.library.fastrGrid.grDevices;
import com.oracle.truffle.r.library.fastrGrid.GridContext;
import com.oracle.truffle.r.library.fastrGrid.GridState;
import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RNull;
/**
* Node that handles the {@code C_X11} external calls. Those calls may be initiated from either the
* {@code X11} function or FastR specific {@code awt} function. In either case the result is that
* the AWT window is opened and ready for drawing.
*/
public final class InitWindowedDevice extends RExternalBuiltinNode {
static {
Casts.noCasts(InitWindowedDevice.class);
}
public FastRComponent getFastRComponent() {
return fastRComponent;
@Override
protected Object call(RArgsValuesAndNames args) {
GridState gridState = GridContext.getContext().getGridState();
if (!gridState.isDeviceInitialized()) {
GridContext.getContext().getCurrentDevice().openNewPage();
gridState.setDeviceInitialized();
}
RGridGraphicsAdapter.setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo");
return RNull.instance;
}
}
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
eval(expression({
# This should be preffered way of starting the FastR java device.
# For compatibility reasons, both X11 and awt end up calling C_X11.
# In the future, this function may support extra parameters like a
# reference to java 2D graphics object, which will be used for the drawing.
awt <- function(...) {
.External2(grDevices:::C_X11)
}
}), asNamespace("grDevices"))
\ No newline at end of file
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Compatibility layer for grDevices packages.
*
* With FastR grid we use {@link com.oracle.truffle.r.library.fastrGrid.device.GridDevice} instead
* of the abstraction used by GnuR. This is compatibility layer that provides implementation of some
* of the externals that manipulate the device and forwards them to corresponding methods on FastR
* grid side.
*/
package com.oracle.truffle.r.library.fastrGrid.grDevices;
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2017, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.fastrGrid.graphics;
import com.oracle.truffle.r.library.fastrGrid.FastRGridExternalLookup;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RError.Message;
import com.oracle.truffle.r.runtime.ROptions;
import com.oracle.truffle.r.runtime.ROptions.OptionsException;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RPairList;
import com.oracle.truffle.r.runtime.env.REnvironment;
/**
* Initialization of graphics package emulation for the purposes of FastR grid package
* implementation.
*
* FastR exposes two devices: the null device and 'awt' device, and adds function 'awt' to the
* grDevices package. The 'awt' function ends up calling 'C_X11' (the same as the 'X11' function
* from grDevices), we capture that call in {@link FastRGridExternalLookup} and replace it with our
* own logic. This way we also "implement" 'X11' device with java awt should anyone try to activate
* it.
*
* Moreover, we change the value of option "device" to our "awt" function so that when e.g. lattice
* tries to open the default device it uses 'awt'. If the future this should be either 'awt' for
* interactive sessions, or some image format device for batch sessions. We should also honor the
* R_INTERACTIVE_DEVICE and R_DEFAULT_DEVICE environment variables.
*/
public class RGridGraphicsAdapter {
private static final String NULL_DEVICE = "null device";
/**
* The graphics devices system maintains two variables .Device and .Devices in the base
* environment both are always set: .Devices gives a list of character vectors of the names of
* open devices, .Device is the element corresponding to the currently active device. The null
* device will always be open.
*/
private static final String DOT_DEVICE = ".Device";
private static final String DOT_DEVICES = ".Devices";
public static void initialize() {
setCurrentDevice(NULL_DEVICE);
ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
try {
options.setValue("device", "awt");
} catch (OptionsException e) {
RError.warning(RError.NO_CALLER, Message.GENERIC, "FastR could not set the 'device' options to awt.");
}
}
public static void setCurrentDevice(String name) {
REnvironment baseEnv = REnvironment.baseEnv();
baseEnv.safePut(DOT_DEVICE, name);
Object devices = baseEnv.get(DOT_DEVICES);
if (devices instanceof RPairList) {
((RPairList) devices).appendToEnd(RDataFactory.createPairList(name));
} else {
baseEnv.safePut(DOT_DEVICES, RDataFactory.createPairList(name));
}
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2017, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.grDevices;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen;
import com.oracle.truffle.r.library.grDevices.pdf.PdfGraphicsDevice;
import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.nodes.unary.CastNode;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
public class DevicesCCalls {
public abstract static class C_DevOff extends RExternalBuiltinNode.Arg1 {
public static C_DevOff create() {
return C_DevOffNodeGen.create();
}
static {
Casts casts = new Casts(C_DevOff.class);
casts.arg(0).asIntegerVector().findFirst();
}
@Specialization
public Object doCall(int deviceIndex) {
GraphicsEngineImpl.getInstance().killGraphicsDeviceByIndex(deviceIndex);
return RNull.instance;
}
}
public static final class C_DevCur extends RExternalBuiltinNode.Arg0 {
@Override
@TruffleBoundary
public Object execute() {
return GraphicsEngineImpl.getInstance().getCurrentGraphicsDeviceIndex();
}
}
public static final class C_PDF extends RExternalBuiltinNode {
@Child private CastNode extractFontsNode = newCastBuilder().mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode();
@Child private CastNode asStringNode = newCastBuilder().asStringVector().findFirst().buildCastNode();
@Child private CastNode asDoubleNode = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
@Child private CastNode asLogicalNode = newCastBuilder().asLogicalVector().findFirst().buildCastNode();
@Child private CastNode asIntNode = newCastBuilder().asIntegerVector().findFirst().buildCastNode();
static {
Casts.noCasts(C_PDF.class);
}
@SuppressWarnings("unused")
@Override
@TruffleBoundary
public Object call(RArgsValuesAndNames args) {
new PdfGraphicsDevice(extractParametersFrom(args));
// todo implement devices addition
return RNull.instance;
}
private PdfGraphicsDevice.Parameters extractParametersFrom(RArgsValuesAndNames args) {
PdfGraphicsDevice.Parameters result = new PdfGraphicsDevice.Parameters();
result.filePath = asString(args.getArgument(0));
result.paperSize = asString(args.getArgument(1));
result.fontFamily = asString(args.getArgument(2));
result.encoding = asString(args.getArgument(3));
result.bg = asString(args.getArgument(4));
result.fg = asString(args.getArgument(5));
result.width = asDouble(castVector(args.getArgument(6)));
result.height = asDouble(castVector(args.getArgument(7)));
result.pointSize = asDouble(castVector(args.getArgument(8)));
result.oneFile = asLogical(castVector(args.getArgument(9)));
result.pageCenter = asLogical(castVector(args.getArgument(10)));
result.title = asString(args.getArgument(11));
result.fonts = extractFontsFrom(args.getArgument(12));
result.majorVersion = asInt(castVector(args.getArgument(13)));
result.minorVersion = asInt(castVector(args.getArgument(14)));
result.colormodel = asString(args.getArgument(15));
result.useDingbats = asLogical(castVector(args.getArgument(16)));
result.useKerning = asLogical(castVector(args.getArgument(17)));
result.fillOddEven = asLogical(castVector(args.getArgument(18)));
result.compress = asLogical(castVector(args.getArgument(19)));
return result;
}
private String asString(Object value) {
return (String) asStringNode.execute(value);
}
private int asInt(Object value) {
return (Integer) asIntNode.execute(value);
}
private double asDouble(Object value) {
return (Double) asDoubleNode.execute(value);
}
private byte asLogical(Object value) {
return (Byte) asLogicalNode.execute(value);
}
private String[] extractFontsFrom(Object inputArgument) {
return ((RAbstractStringVector) extractFontsNode.execute(inputArgument)).materialize().getDataCopy();
}
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2015, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.grDevices;
import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
public final class NullGraphicsDevice implements GraphicsDevice {
private static final NullGraphicsDevice instance = new NullGraphicsDevice();
public static NullGraphicsDevice getInstance() {
return instance;
}
@Override
public void deactivate() {
throw createExceptionForMethod("deactivate");
}
@Override
public void activate() {
throw createExceptionForMethod("activate");
}
@Override
public void close() {
throw createExceptionForMethod("close");
}
@Override
public DrawingParameters getDrawingParameters() {
throw createExceptionForMethod("getDrawingParameters");
}
@Override
public void setMode(Mode newMode) {
throw createExceptionForMethod("setMode");
}
@Override
public Mode getMode() {
throw createExceptionForMethod("getMode");
}
@Override
public void setClipRect(double x1, double y1, double x2, double y2) {
throw createExceptionForMethod("setClipRect");
}
@Override
public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
throw createExceptionForMethod("drawPolyline");
}
private static RuntimeException createExceptionForMethod(String methodName) {
return new IllegalStateException("Call to " + methodName + " of Null-device");
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2016, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.grDevices.fastrgd;
import static com.oracle.truffle.r.library.graphics.core.geometry.AxisDirection.EAST;
import static com.oracle.truffle.r.library.graphics.core.geometry.AxisDirection.NORTH;
import java.util.Arrays;
import java.util.function.Function;
import com.oracle.truffle.r.library.graphics.FastRFrame;
import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
import com.oracle.truffle.r.library.graphics.core.drawables.DrawableObject;
import com.oracle.truffle.r.library.graphics.core.drawables.PolylineDrawableObject;
import com.oracle.truffle.r.library.graphics.core.drawables.StringDrawableObject;
import com.oracle.truffle.r.library.graphics.core.geometry.Axis;
import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
import com.oracle.truffle.r.library.graphics.core.geometry.CoordinatesFactory;
import com.oracle.truffle.r.library.graphics.core.geometry.DoubleCoordinates;
/**
* Default interactive FastR graphics device.
*/
public class FastRGraphicsDevice implements GraphicsDevice {
private static final double GNUR_DEFAULT_MAX_X = 1;
private static final Axis GNUR_DEFAULT_X_AXIS = new Axis(0, GNUR_DEFAULT_MAX_X, EAST);
private static final Axis GNUR_DEFAULT_Y_AXIS = new Axis(0, 1, NORTH);
private static final double MARGIN = GNUR_DEFAULT_MAX_X * 0.1; // the margin for each side of
// 10% of a screen
// compress resulting image to have a small margin on all sides
private static final double COMPRESS_RATION = 1. - MARGIN * 1.8;
private Mode mode = Mode.GRAPHICS_OFF;
private FastRFrame fastRFrame;
private CoordinateSystem currentCoordinateSystem = new CoordinateSystem(GNUR_DEFAULT_X_AXIS, GNUR_DEFAULT_Y_AXIS);
@Override
public void deactivate() {
// todo impl
}
@Override
public void activate() {
// todo impl
}
@Override
public void close() {
// todo impl
}
@Override
public DrawingParameters getDrawingParameters() {
return null;
}
@Override
public void setMode(Mode newMode) {
mode = newMode;
}
@Override
public Mode getMode() {
return mode;
}
@Override
public void setClipRect(double x1, double y1, double x2, double y2) {
// todo impl
}
@Override
public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
// todo continue from GEPolyline() of engine.c
Coordinates convertedCoords = CoordinatesFactory.withRatioAndShift(coordinates, COMPRESS_RATION, MARGIN);
addDrawableObject(new PolylineDrawableObject(currentCoordinateSystem, convertedCoords));
drawBounds();
drawXYLabelsFor(coordinates);
}
private void drawBounds() {
// x,y in range [0,1]
double[] boundsXYPairs = {0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0};
Coordinates bounds = CoordinatesFactory.createByXYPairs(boundsXYPairs);
Coordinates compressedBounds = CoordinatesFactory.withRatioAndShift(bounds, COMPRESS_RATION, MARGIN);
addDrawableObject(new PolylineDrawableObject(currentCoordinateSystem, compressedBounds));
}
private void drawXYLabelsFor(Coordinates coordinates) {
drawLabelsForCoordinates(coordinates.getXCoordinatesAsDoubles(), MARGIN, 0.01, // just small
// shift
d -> CoordinatesFactory.createWithSameY(d, 0));
drawLabelsForCoordinates(coordinates.getYCoordinatesAsDoubles(), 0, MARGIN, d -> CoordinatesFactory.createWithSameX(0, d));
}
private void drawLabelsForCoordinates(double[] coordinates, double xShift, double yShift, Function<double[], DoubleCoordinates> xYConverter) {
int length = coordinates.length;
double[] sortedCoords = new double[length];
// copy to avoid side-effects on a caller side
System.arraycopy(coordinates, 0, sortedCoords, 0, length);
Arrays.sort(sortedCoords);
String[] labels = composeLabelsFor(sortedCoords);
DoubleCoordinates xYCoords = xYConverter.apply(sortedCoords);
Coordinates shiftedCoords = CoordinatesFactory.withRatioAndShift(xYCoords, COMPRESS_RATION, xShift, yShift);
addDrawableObject(new StringDrawableObject(currentCoordinateSystem, shiftedCoords, labels));
}
private static String[] composeLabelsFor(double[] doubles) {
return Arrays.stream(doubles).mapToObj(String::valueOf).toArray(String[]::new);
}
private FastRFrame getFastRFrame() {
if (fastRFrame == null || !fastRFrame.isVisible()) {
fastRFrame = new FastRFrame();
fastRFrame.setVisible(true);
}
return fastRFrame;
}
private void addDrawableObject(DrawableObject drawableObject) {
getFastRFrame().getFastRComponent().addDrawableObject(drawableObject);
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2015, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.grDevices.pdf;
import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
import com.oracle.truffle.r.runtime.RRuntime;
public class PdfGraphicsDevice implements GraphicsDevice {
@SuppressWarnings("unused") private final Parameters deviceParameters;
public PdfGraphicsDevice(Parameters deviceParameters) {
this.deviceParameters = deviceParameters;
}
@Override
public void deactivate() {
}
@Override
public void activate() {
}
@Override
public void close() {
}
@Override
public DrawingParameters getDrawingParameters() {
return null;
}
@Override
public void setMode(Mode newMode) {
}
@Override
public Mode getMode() {
return null;
}
@Override
public void setClipRect(double x1, double y1, double x2, double y2) {
}
@Override
public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
}
public static class Parameters {
public String filePath;
public String paperSize = "special";
public String fontFamily = "Helvetica";
public String encoding = "default";
public String bg = "transparent";
public String fg = "black";
public double width = 7.;
public double height = 7.;
public double pointSize = 12.;
public byte oneFile = RRuntime.LOGICAL_TRUE;
public byte pageCenter = RRuntime.LOGICAL_TRUE;
public String title = "R Graphics Output";
public String[] fonts;
public int majorVersion = 1;
public int minorVersion = 4;
public String colormodel = "srgb";
public byte useDingbats = RRuntime.LOGICAL_TRUE;
public byte useKerning = RRuntime.LOGICAL_TRUE;
public byte fillOddEven = RRuntime.LOGICAL_FALSE;
public byte compress = RRuntime.LOGICAL_TRUE;
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2015, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.graphics;
import com.oracle.truffle.r.library.graphics.core.AbstractGraphicsSystem;
/**
* Denotes to the 'base' in GNUR terms graphics system.
*/
public class BaseGraphicsSystem extends AbstractGraphicsSystem {
private final GraphicsEventsListener graphicsEventsListener = (graphicsEvent, graphicsDevice) -> {
};
@Override
public GraphicsEventsListener getGraphicsEventsListener() {
return graphicsEventsListener;
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2016, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.graphics;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JComponent;
import com.oracle.truffle.r.library.graphics.core.drawables.DrawableObject;
import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
public class FastRComponent extends JComponent {
private static final long serialVersionUID = 1L;
private final List<DrawableObject> displayList = Collections.synchronizedList(new ArrayList<>());
private boolean shouldDraw;
private CoordinateSystem coordinateSystem;
/**
* Note! Called from ED thread.
*/
@Override
public void doLayout() {
super.doLayout();
Dimension size = getSize();
coordinateSystem = new CoordinateSystem(0, size.getWidth(), 0, size.getHeight());
shouldDraw = true;
recalculateDisplayList();
}
private void recalculateDisplayList() {
synchronized (displayList) {
displayList.stream().forEach(drawableObject -> drawableObject.recalculateForDrawingIn(coordinateSystem));
}
}
/**
* Note! Called from ED thread.
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (shouldDraw) {
drawDisplayListOn(g2);
}
}
private void drawDisplayListOn(Graphics2D g2) {
synchronized (displayList) {
displayList.stream().forEach(drawableObject -> drawableObject.drawOn(g2));
}
}
public void addDrawableObject(DrawableObject drawableObject) {
synchronized (displayList) {
displayList.add(drawableObject);
}
shouldDraw = true;
if (coordinateSystem != null) {
drawableObject.recalculateForDrawingIn(coordinateSystem);
repaint();
}
}
}
/*
* 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) 1995, 1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998 Ross Ihaka
* Copyright (c) 1998--2014, The R Core Team
* Copyright (c) 2002--2010, The R Foundation
* Copyright (C) 2005--2006, Morten Welinder
* Copyright (c) 2014, 2017, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.library.graphics;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
import com.oracle.truffle.r.library.graphics.core.GraphicsEngine;
import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl;
import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
import com.oracle.truffle.r.library.graphics.core.geometry.CoordinatesFactory;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.nodes.unary.CastNode;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RDoubleVector;
import com.oracle.truffle.r.runtime.data.RNull;
public class GraphicsCCalls {
public static final class C_PlotXY extends RExternalBuiltinNode {
@Child private CastNode castXYNode = newCastBuilder().mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
static {
Casts.noCasts(C_PlotXY.class);
}
@Override
@TruffleBoundary
public RNull call(RArgsValuesAndNames args) {
RDoubleVector xyVector = (RDoubleVector) castXYNode.execute(args.getArgument(0));
getGraphicsEngine().setCurrentGraphicsDeviceMode(GraphicsDevice.Mode.GRAPHICS_ON);
drawWithLines(xyVector);
return RNull.instance;
}
private static void drawWithLines(RDoubleVector xyVector) {
// todo implement coordinate systems units conversion like in GConvert (graphics.c)
setClipRect();
DrawingParameters adoptedParameters = adoptCurrentDeviceDrawingParameters();
Coordinates coordinates = CoordinatesFactory.createByXYVector(xyVector);
getGraphicsEngine().drawPolyline(coordinates, adoptedParameters);
}
private static DrawingParameters adoptCurrentDeviceDrawingParameters() {
// todo Now adoption as for today. Transcribe from gcontextFromGM() (graphics.c)
return getCurrentGraphicsDevice().getDrawingParameters();
}
private static void setClipRect() {
// todo Transcrive from Gclip() (graphics.c)
getGraphicsEngine().setCurrentGraphicsDeviceClipRect(0, 0, 0, 0);
}
private static GraphicsDevice getCurrentGraphicsDevice() {
return getGraphicsEngine().getCurrentGraphicsDevice();
}
private static GraphicsEngine getGraphicsEngine() {
return GraphicsEngineImpl.getInstance();
}
}
public static final class C_Par extends RExternalBuiltinNode {
static {
Casts.noCasts(C_Par.class);
}
@Override
@TruffleBoundary
public Object call(RArgsValuesAndNames args) {
// pch
return RDataFactory.createIntVectorFromScalar(1);
}
}
@SuppressWarnings("unused")
public static final class C_mtext extends RExternalBuiltinNode {
private Object text;
private double side = 3.;
private double line = 0.;
private boolean outer = true;
private double adj = RRuntime.DOUBLE_NA;
private double at = RRuntime.DOUBLE_NA;
private double padj = RRuntime.DOUBLE_NA;
private double cex = RRuntime.DOUBLE_NA;
private double col = RRuntime.DOUBLE_NA;
private double font = RRuntime.DOUBLE_NA;
@Child private CastNode firstDoubleCast = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
static {
Casts.noCasts(C_mtext.class);
}
@Override
@TruffleBoundary
public Object call(RArgsValuesAndNames args) {
extractArgumentsFrom(args);
return RNull.instance;
}
private void extractArgumentsFrom(RArgsValuesAndNames args) {
// text = args.getArgument(0); // postpone for now
side = extractFirstDoubleValueFrom(args.getArgument(1));
line = extractFirstDoubleValueFrom(args.getArgument(2));
// outer = extractFirstDoubleValueFrom(args.getArgument(3));
at = extractFirstDoubleValueFrom(args.getArgument(4));
adj = extractFirstDoubleValueFrom(args.getArgument(5));
padj = extractFirstDoubleValueFrom(args.getArgument(6));
cex = extractFirstDoubleValueFrom(args.getArgument(7));
// col = extractFirstDoubleValueFrom(args.getArgument(8));
font = extractFirstDoubleValueFrom(args.getArgument(9));
}
private double extractFirstDoubleValueFrom(Object arg) {
return (Double) firstDoubleCast.execute(arg);
}
}
}
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