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

FastR Grid: devices that save images support %d placeholder for filenames.

parent fa3be837
No related branches found
No related tags found
No related merge requests found
Showing
with 154 additions and 19 deletions
......@@ -28,6 +28,7 @@ import java.util.ArrayList;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice;
......@@ -59,7 +60,7 @@ public final class GridContext {
private int currentDeviceIdx = 0;
private GridContext() {
devices.add(new DeviceAndState(null));
devices.add(new DeviceAndState(null, null));
}
public static GridContext getContext() {
......@@ -86,10 +87,15 @@ public final class GridContext {
}
public void setCurrentDevice(String name, GridDevice currentDevice) {
assert !(currentDevice instanceof FileGridDevice) : "FileGridDevice must have filenamePattern";
setCurrentDevice(name, currentDevice, null);
}
public void setCurrentDevice(String name, GridDevice currentDevice, String filenamePattern) {
RGridGraphicsAdapter.addDevice(name);
RGridGraphicsAdapter.setCurrentDevice(name);
currentDeviceIdx = this.devices.size();
this.devices.add(new DeviceAndState(currentDevice));
this.devices.add(new DeviceAndState(currentDevice, filenamePattern));
assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
}
......@@ -158,9 +164,9 @@ public final class GridContext {
final GridDevice device;
final GridDeviceState state;
DeviceAndState(GridDevice device) {
DeviceAndState(GridDevice device, String filenamePattern) {
this.device = device;
this.state = new GridDeviceState();
this.state = new GridDeviceState(filenamePattern);
}
}
}
......@@ -15,6 +15,7 @@ import java.util.function.Supplier;
import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
import com.oracle.truffle.r.library.fastrGrid.grDevices.FileDevUtils;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.env.REnvironment;
......@@ -163,6 +164,10 @@ public final class GridState {
return devState.scale;
}
public String getNextPageFilename() {
return FileDevUtils.formatFilename(devState.filenamePattern, devState.pageIndex++);
}
public static final class GridPalette {
public final GridColor[] colors;
public final String[] colorNames;
......@@ -194,5 +199,11 @@ public final class GridState {
private boolean isDisplayListOn = true;
private RList displayList;
private int displayListIndex = 0;
private int pageIndex = 2;
private String filenamePattern;
GridDeviceState(String filenamePattern) {
this.filenamePattern = filenamePattern;
}
}
}
......@@ -14,8 +14,11 @@ package com.oracle.truffle.r.library.fastrGrid;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.runtime.RError.Message;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RNull;
......@@ -40,8 +43,17 @@ final class LNewPage extends RExternalBuiltinNode {
}
@TruffleBoundary
private static void openNewPage(GridDevice device) {
device.openNewPage();
private void openNewPage(GridDevice device) {
if (device instanceof FileGridDevice) {
String path = GridContext.getContext().getGridState().getNextPageFilename();
try {
((FileGridDevice) device).openNewPage(path);
} catch (DeviceCloseException e) {
throw error(Message.GENERIC, "Cannot save the image. Details: " + e.getMessage());
}
} else {
device.openNewPage();
}
}
@Override
......
/*
* 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.device;
/**
* Should be implemented by devices that save their output into a file. Such devices should only
* accept complete filenames, i.e. without '%d' placeholder, and the handling of the placeholder is
* left up to the calling code.
*/
public interface FileGridDevice extends GridDevice {
/**
* Each call to {@link #openNewPage()} should save the current image (into the current path) and
* start drawing a new image into the given path, i.e. the given path becomes a new current
* path.
*
* @param filename tha path where to save the next image, will not contain '%d' symbol as its
* processing should be handled by the caller.
* @throws DeviceCloseException
*/
void openNewPage(String filename) throws DeviceCloseException;
}
......@@ -39,10 +39,10 @@ import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.Utils;
public class SVGDevice implements GridDevice {
public class SVGDevice implements GridDevice, FileGridDevice {
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000");
private final StringBuilder data = new StringBuilder(1024);
private final String filename;
private String filename;
private final double width;
private final double height;
......@@ -73,14 +73,16 @@ public class SVGDevice implements GridDevice {
height);
}
@Override
public void openNewPage(String newFilename) throws DeviceCloseException {
saveFile();
filename = newFilename;
openNewPage();
}
@Override
public void close() throws DeviceCloseException {
closeSVGDocument();
try {
Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new DeviceCloseException(e);
}
saveFile();
}
@Override
......@@ -181,7 +183,19 @@ public class SVGDevice implements GridDevice {
data.append("' ").append(attributes).append(" />");
}
private void saveFile() throws DeviceCloseException {
closeSVGDocument();
try {
Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new DeviceCloseException(e);
}
}
private void closeSVGDocument() {
if (data.length() == 0) {
return;
}
if (cachedCtx != null) {
// see #appendStyle
append("</g>");
......
......@@ -32,10 +32,12 @@ import java.io.IOException;
import javax.imageio.ImageIO;
public final class BufferedImageDevice extends Graphics2DDevice {
import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
public final class BufferedImageDevice extends Graphics2DDevice implements FileGridDevice {
private final BufferedImage image;
private final String filename;
private final String fileType;
private String filename;
private BufferedImageDevice(String filename, String fileType, BufferedImage image, Graphics2D graphics, int width, int height) {
super(graphics, width, height, true);
......@@ -56,8 +58,19 @@ public final class BufferedImageDevice extends Graphics2DDevice {
return new BufferedImageDevice(filename, fileType, image, graphics, width, height);
}
@Override
public void openNewPage(String newFilename) throws DeviceCloseException {
saveImage();
filename = newFilename;
openNewPage();
}
@Override
public void close() throws DeviceCloseException {
saveImage();
}
private void saveImage() throws DeviceCloseException {
try {
ImageIO.write(image, fileType, new File(filename));
} catch (IOException e) {
......
......@@ -48,7 +48,7 @@ public class DevCairo extends RExternalBuiltinNode {
throw error(Message.INVALID_ARG_TYPE);
}
GridContext.getContext().setCurrentDevice("svg", new SVGDevice(filename, witdh / 72., height / 72.));
GridContext.getContext().setCurrentDevice("svg", new SVGDevice(FileDevUtils.formatInitialFilename(filename), witdh / 72., height / 72.), filename);
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.
*/
package com.oracle.truffle.r.library.fastrGrid.grDevices;
import com.oracle.truffle.api.CompilerAsserts;
public class FileDevUtils {
public static String formatInitialFilename(String filename) {
return formatFilename(filename, 1);
}
public static String formatFilename(String filename, int pageIndex) {
CompilerAsserts.neverPartOfCompilation();
assert filename != null;
assert pageIndex >= 1;
return String.format(filename, pageIndex);
}
}
......@@ -100,8 +100,8 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
String formatName = name.substring(0, name.indexOf("::"));
String filename = name.substring(name.lastIndexOf(':') + 1);
try {
BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, width, height);
GridContext.getContext().setCurrentDevice(formatName.toUpperCase(), device);
BufferedImageDevice device = BufferedImageDevice.open(FileDevUtils.formatInitialFilename(filename), formatName, width, height);
GridContext.getContext().setCurrentDevice(formatName.toUpperCase(), device, filename);
} catch (NotSupportedImageFormatException e) {
throw error(Message.GENERIC, String.format("Format '%s' is not supported.", formatName));
}
......
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