1

I am creating a program using processing(java) that outputs an SVG file for me to add it to PowerPoint and other programs.

I figured it would be a lot more convenient for the program to directly copy the generated file to my system clipboard, instead of having to copy the file from the output directory.

The trouble is that I can't find a way to set the contents of the clipboard to an SVG file. I've found ways that work with images, but not SVG. To clarify, I want the pasted file to be an SVG too because I want to edit the shapes and lines in PowerPoint afterward.

I am also open to javascript solutions which may work on the web. The goal is to be able to paste an editable collection of shapes, lines, and texts into PowerPoint.

All help is appreciated, thanks in advance!

Edit: Here is the code that works for images:

import java.awt.image.*;
import java.awt.*;
import java.awt.datatransfer.*;
import javax.imageio.*;

void setup() {
  size(200, 200);
  background(0);
  Image img=null;
  try {
    img = ImageIO.read(new File("path/to/file.jpg"));//path to image file
  } 
  catch (IOException e) {
    print(e);
  }

  ImageSelection imageSelection = new ImageSelection(img);
  Toolkit toolkit = Toolkit.getDefaultToolkit();
  toolkit.getSystemClipboard().setContents(imageSelection, null);
}
void draw() {
}
public class ImageSelection implements Transferable {
  private Image image;



  public ImageSelection(Image image) {
    this.image = image;//added on
  }

  public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
    if (flavor.equals(DataFlavor.imageFlavor) == false) {
      throw new UnsupportedFlavorException(flavor);//usually with transferable
    }
    return image;
  }

  public boolean isDataFlavorSupported(DataFlavor flavor) {
    return flavor.equals(DataFlavor.imageFlavor);//usually with transferable
  }

  public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] {
      DataFlavor.imageFlavor//usually with transferable
    };
  }
}


limse10
  • 35
  • 4

1 Answers1

1

There is a bit of confusion with the code you posted: so far it looks like for some reason you want to load an image and copy that to the clipboard, not an SVG.

If you want to copy an SVG to the clipboard for PowerPoint there are a few hoops to jump through:

  1. Use the PShapeSVG source code to understand to get the SVG markup
  2. Use the right MIME type: I simply tried this solution

Putting it together:

import processing.svg.*;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Writer;

import java.nio.charset.StandardCharsets;

import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;

void setup(){

  PGraphicsSVG svg = (PGraphicsSVG)createGraphics(300,300,SVG);
  svg.beginDraw();

  svg.background(#4db748);
  svg.noFill();
  svg.strokeWeight(27);
  int a = 80;
  int b = 220;
  svg.line(a,a,b,b);
  svg.line(a,b,b,a);
  svg.line(a,a,b,a);
  svg.line(a,b,b,b);
  svg.ellipse(150, 150, 250, 250);

  copyToClipboard(svg);

  // normally you would call endDraw, but this will obviously throw an error if you didn't specify a filename in createGraphics()
  //svg.endDraw();

  println("svg copied to clipboard");
  exit();
}

String getSVGString(PGraphicsSVG svg){
  // make a binary output stream
  ByteArrayOutputStream output = new ByteArrayOutputStream();
  // make a writer for it
  Writer writer = PApplet.createWriter(output);
  // same way the library writes to disk we write to the byte array stream
  try{
    ((SVGGraphics2D) svg.g2).stream(writer, false);
  } catch (SVGGraphics2DIOException e) {
      e.printStackTrace();
  }
  // convert bytes to an UTF-8 encoded string
  return new String( output.toByteArray(), StandardCharsets.UTF_8 );
}

void copyToClipboard(PGraphicsSVG svg){
  // get the SVG markup as a string
  String svgString = getSVGString(svg);
  println(svgString);
  // access the system clipboard
  Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
  // get an binary clipboard with the correct SVG MIME type
  SvgClip strSVG = new SvgClip(svgString);
  // commit the clipboard encoded SVG to clipboard 
  clip.setContents(strSVG, null);
}

// blatant copy/adapation of https://stackoverflow.com/questions/33726321/how-to-transfer-svg-image-to-other-programs-with-dragndrop-in-java
class SvgClip implements Transferable{

    String svgString;

    DataFlavor svgFlavor = new DataFlavor("image/svg+xml; class=java.io.InputStream","Scalable Vector Graphic");

    DataFlavor [] supportedFlavors = {svgFlavor};

    SvgClip(String svgString){
        this.svgString = svgString;

        SystemFlavorMap systemFlavorMap = (SystemFlavorMap) SystemFlavorMap.getDefaultFlavorMap();
        systemFlavorMap.addUnencodedNativeForFlavor(svgFlavor, "image/svg+xml");
    }

    @Override public DataFlavor[] getTransferDataFlavors(){
          return this.supportedFlavors;    
    }

    @Override public boolean isDataFlavorSupported(DataFlavor flavor){
       return true;
    }

    @Override public Object getTransferData(DataFlavor flavor)
            throws UnsupportedFlavorException, IOException{
        return new ByteArrayInputStream(svgString.getBytes(StandardCharsets.UTF_8));
    }

}

Note Call copyToClipboard(svg) after your last drawing command, but before PGraphicsSVG's endDraw() call (otherwise it will return an empty SVG document)

The result in PowerPoint:

XR logo approximation pasted from Processing generated SVG as PowerPoint Clipboard

George Profenza
  • 45,059
  • 16
  • 133
  • 201
  • Oh my gosh, this worked PERFECTLY. I had to edit the svg section because I wanted to draw lines with dasharrays but the PShapeSVG did not have support for that as far as I could find. But I wrote my custom SVG maker and now it works like a charm. This is amazing, thank you so much. You're doing gods work my man. – limse10 Apr 18 '20 at 14:19