[Feature] Copy in vector format

Ideas that we are planning to implement in the near future

Re: [Feature] Copy in vector format

Postby Steren on Thu, 22 Oct 2009 10:55:16 GMT

Indeed, we should only take what is needed from the Batik library. I will give you a list of needed .jar. I can tell right now that batik-svggen.jar and batik-dom.jar are required.

I generated the patch using the svn command (I'm not so used to NetBeans). Here is what I do to apply it to a new checkout of Alchemy :
Code: Select all
steren@steren-portable:~$ svn co http://svn.al.chemy.org/svn AlchemyTest
steren@steren-portable:~$ cp SVG_switch.patch AlchemyTest/Alchemy/
steren@steren-portable:~/AlchemyTest/Alchemy$ patch -p0 < SVG_switch.patch


Anyway, here is a patch generated from NetBeans (now that I found this "export diff" menu):
Code: Select all
# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /home/steren/Alchemy/Alchemy/src/org/alchemy/core
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: AlcMenuBar.java
--- AlcMenuBar.java Base (BASE)
+++ AlcMenuBar.java Locally Modified (Based On LOCAL)
@@ -2,6 +2,7 @@
  *  This file is part of the Alchemy project - http://al.chemy.org
  *
  *  Copyright (c) 2007-2009 Karl D.D. Willis
+ *  Copyright (c) 2009 Steren Giannini (steren.giannini@gmail.com)
  *
  *  Alchemy is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -552,7 +553,40 @@
         switchVectorAppItem.setup(setVectorApp);
         switchMenu.add(switchVectorAppItem);

+        // Format submenu
+        AlcMenu formatMenu = new AlcMenu(getS("setVectorFormat"));
+        ButtonGroup formatGroup = new ButtonGroup();
+        //PDF
+        AlcRadioButtonMenuItem pdfItem = new AlcRadioButtonMenuItem(Alchemy.preferences.FORMAT_PDF, "PDF");
+        if (Alchemy.preferences.switchVectorFormat == Alchemy.preferences.FORMAT_PDF) {
+            pdfItem.setSelected(true);
+        }
+        pdfItem.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                AlcRadioButtonMenuItem source = (AlcRadioButtonMenuItem) e.getSource();
+                Alchemy.preferences.switchVectorFormat = source.getIndex();
+            }
+        });
+        formatGroup.add(pdfItem);
+        formatMenu.add(pdfItem);
+        //SVG
+        AlcRadioButtonMenuItem svgItem = new AlcRadioButtonMenuItem(Alchemy.preferences.FORMAT_SVG, "SVG");
+        if (Alchemy.preferences.switchVectorFormat == Alchemy.preferences.FORMAT_SVG) {
+            svgItem.setSelected(true);
+        }
+        svgItem.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                AlcRadioButtonMenuItem source = (AlcRadioButtonMenuItem) e.getSource();
+                Alchemy.preferences.switchVectorFormat = source.getIndex();
+            }
+        });
+        formatGroup.add(svgItem);
+        formatMenu.add(svgItem);

+        formatMenu.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 5));
+        switchMenu.add(formatMenu);
+
+
         // Switch Bitmap App
         final String setBitmapApp = getS("setBitmapApp");
         AbstractAction switchBitmapAppAction = new AbstractAction() {
@@ -770,6 +804,7 @@
         fc.setFileFilter(new ExportFileFilter("PNG"));
         fc.setFileFilter(new ExportFileFilter("JPG"));
         fc.setFileFilter(new ExportFileFilter("PDF"));
+        fc.setFileFilter(new ExportFileFilter("SVG"));
         fc.setSelectedFile(new File(Alchemy.bundle.getString("defaultFileName")));

         // in response to a button click:
@@ -791,6 +826,8 @@
                 Alchemy.canvas.saveBitmap(file);
             } else if (format.equals("PNG - Transparent")) {
                 Alchemy.canvas.saveBitmap(file, true);
+            } else if (format.equals("SVG")) {
+                Alchemy.session.saveSVG(file);
             }
         }
     }
@@ -810,13 +847,25 @@
     /** Make a temporary file, create a PDF, and then open it */
     private void switchVector() {
         try {
+            if(Alchemy.preferences.switchVectorFormat == Alchemy.preferences.FORMAT_SVG) {
+                File tempVector = File.createTempFile("AlchemyTempVectorFile", ".svg");
+                tempVector.deleteOnExit();
+                if (Alchemy.session.saveSVG(tempVector)) {
+                    openSwitch(tempVector.toString(), Alchemy.preferences.switchVectorApp);
+                } else {
+                    System.out.println("Didn't save SVG");
+                }
+            } else {  //Otherwise, save to pdf
             File tempVector = File.createTempFile("AlchemyTempVectorFile", ".pdf");
             tempVector.deleteOnExit();
             if (Alchemy.session.saveSinglePdf(tempVector)) {
                 openSwitch(tempVector.toString(), Alchemy.preferences.switchVectorApp);
             } else {
-                System.out.println("Didn't save???");
+                    System.out.println("Didn't save PDF");
             }
+            }
+
+
         } catch (IOException ex) {
             System.err.println(ex);
         }
Index: AlcPreferences.java
--- AlcPreferences.java Base (BASE)
+++ AlcPreferences.java Locally Modified (Based On LOCAL)
@@ -42,6 +42,11 @@
     /** Preferences package */
     static Preferences prefs;
     //////////////////////////////////////////////////////////////
+    //  DEFINE CONSTANTS
+    //////////////////////////////////////////////////////////////
+    public final int FORMAT_PDF = 0;
+    public final int FORMAT_SVG = 1;
+    //////////////////////////////////////////////////////////////
     //  WINDOW LAYOUT
     //////////////////////////////////////////////////////////////
     /** The preferences window */
@@ -119,6 +124,8 @@
     //////////////////////////////////////////////////////////////
     /** Switch Vector Application */
     String switchVectorApp;
+    /** What format when Switch to Vector Application */
+    int switchVectorFormat;
     /** Switch Bitmap Application */
     String switchBitmapApp;
     //////////////////////////////////////////////////////////////
@@ -175,6 +182,7 @@
         shapesPath = prefs.get("Shapes Path", new File("shapes").getAbsolutePath());

         switchVectorApp = prefs.get("Switch Vector Application", null);
+        switchVectorFormat = prefs.getInt("Switch Vector Format", 0);
         switchBitmapApp = prefs.get("Switch Bitmap Application", null);

         paletteAttached = prefs.getBoolean("Palette Attached", false);
@@ -223,6 +231,7 @@
         if (switchVectorApp != null) {
             prefs.put("Switch Vector Application", switchVectorApp);
         }
+        prefs.putInt("Switch Vector Format", switchVectorFormat);
         if (switchBitmapApp != null) {
             prefs.put("Switch Bitmap Application", switchBitmapApp);
         }
Index: AlcResourceBundle.properties
--- AlcResourceBundle.properties Base (BASE)
+++ AlcResourceBundle.properties Locally Modified (Based On LOCAL)
@@ -79,6 +79,7 @@
switchVectorTitle = Switch Vector
switchBitmapTitle = Switch Bitmap
setVectorApp = Set Vector Application...
+setVectorFormat = Set Vector Format...
setBitmapApp = Set Bitmap Application...

################################################
Index: AlcResourceBundle_fr.properties
--- AlcResourceBundle_fr.properties Base (BASE)
+++ AlcResourceBundle_fr.properties Locally Modified (Based On LOCAL)
@@ -5,14 +5,14 @@
# Global
################################################
ok = OK
-cancel = Canceller
+cancel = Annuler
replace = Remplacer
yes = Oui
no = Non
open = Ouvrir
save = Sauvegarder
newFolder = Nouveau Dossier
-reset = Reset
+reset = Remise à zéro
select = Sélectionner

################################################
@@ -70,11 +70,12 @@
################################################
# SWITCH MENU
################################################
-switchTitle = Switch
+switchTitle = Basculer

-switchVectorTitle = Switch Vector
-switchBitmapTitle = Switch Bitmap
+switchVectorTitle = Basculer au Format Vectoriel
+switchBitmapTitle = Basculer en Bitmap
setVectorApp = Définir une Application Vectorielle...
+setVectorFormat = Définir le Format Vectoriel...
setBitmapApp = Défenir une Application Bitmap...

################################################
Index: AlcResourceBundle_fr.properties
--- AlcResourceBundle_fr.properties Base (BASE)
+++ AlcResourceBundle_fr.properties Locally Modified (Based On LOCAL)
@@ -1 +0,0 @@
-*
\ No newline at end of file
Index: AlcSession.java
--- AlcSession.java Base (BASE)
+++ AlcSession.java Locally Modified (Based On LOCAL)
@@ -2,6 +2,7 @@
  *  This file is part of the Alchemy project - http://al.chemy.org
  *
  *  Copyright (c) 2007-2009 Karl D.D. Willis
+ *  Copyright (c) 2009 Steren Giannini (steren.giannini@gmail.com)
  *
  *  Alchemy is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -30,6 +31,14 @@
import com.lowagie.text.pdf.*;
import com.lowagie.text.xml.xmp.*;

+// BATIK (for svg)
+import java.awt.Dimension;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.dom.GenericDOMImplementation;
+//import org.w3c.dom.Document; //because of Document class conflict, do not import
+import org.w3c.dom.DOMImplementation;
+
/**
  * Class to control Alchemy 'sessions'
  * Timing, recording, loading of PDF drawing sessions
@@ -278,6 +287,52 @@
         return noError;
     }

+    /** Save the canvas to a single paged SVG file
+     *
+     * @param file  The file object to save the svg to
+     * @return      True if save worked, otherwise false
+     */
+    boolean saveSVG(File file) {
+        boolean noError = true;
+        System.out.println("Save SVG Called: " + file.toString());
+
+        // Get the current 'real' size of the canvas without margins/borders
+        java.awt.Rectangle bounds = Alchemy.canvas.getVisibleRect();
+        // Get a DOMImplementation.
+        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+        // Create an instance of org.w3c.dom.Document.
+        String svgNS = "http://www.w3.org/2000/svg";
+        org.w3c.dom.Document document = domImpl.createDocument(svgNS, "svg", null);
+        //Set custom comment
+        SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
+        ctx.setComment("Generated by Alchemy (http://al.chemy.org) with Batik SVG Generator");
+
+        // Create an instance of the SVG Generator.
+        SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);
+
+        //set the canvas size
+        svgGenerator.setSVGCanvasSize(new Dimension(bounds.width, bounds.height));
+        // Ask vectorCanvas to render into the SVG Graphics2D implementation.
+        Alchemy.canvas.setGuide(false);
+        Alchemy.canvas.vectorCanvas.paintComponent(svgGenerator);
+        Alchemy.canvas.setGuide(true);
+        svgGenerator.dispose();
+           
+        boolean useCSS = true; // we want to use CSS style attributes
+
+        //Write to the file
+        FileWriter out;
+        try {
+            out = new FileWriter(file);
+            svgGenerator.stream(out, useCSS);
+        } catch (IOException ex) {
+            System.err.println(ex);
+            noError = false;
+        }
+
+        return noError;
+    }
+
     /** Adds a pdfReadPage to an existing pdf file
      *
      * @param mainPdf   The main pdf with multiple pages.
User avatar
Steren
 
Posts: 13
Joined: Tue, 18 Aug 2009 21:23:51 GMT
Location: France

Re: [Feature] Copy in vector format

Postby Steren on Thu, 22 Oct 2009 11:20:45 GMT

Alchemy and SVG are doing well when I add this list of Batik libraries :
    dom
    svggen
    awt-util
    css
    parser
    svg-dom
    xml
    ext
    gui-util
    gvt
    util

This list is 2.3 Mo. What do you think ?
User avatar
Steren
 
Posts: 13
Joined: Tue, 18 Aug 2009 21:23:51 GMT
Location: France

Re: [Feature] Copy in vector format

Postby Karl DD on Thu, 22 Oct 2009 12:58:40 GMT

Thanks for that!

Although I am still getting the same "malformed line" errors with the diff file.
It might just be easier to commit it.
I'll send you an email with the details.

Thanks again for your help! Looking forward to trying it out.
User avatar
Karl DD
Site Admin
 
Posts: 592
Joined: Sun, 20 Jan 2008 02:45:28 GMT
Location: Pittsburgh, PA

Previous

Return to Planned Ideas

Who is online

Users browsing this forum: No registered users and 0 guests

cron