From 643e0b8b683629a6bd2e3a0744fa2a80b1490c97 Mon Sep 17 00:00:00 2001
From: tcarver <tjc>
Date: Thu, 15 Nov 2012 12:19:54 +0000
Subject: [PATCH] add svg support

---
 art                                           |   5 +-
 .../artemis/components/FeatureDisplay.java    |  41 ++++-
 uk/ac/sanger/artemis/components/Plot.java     |  26 ++-
 .../artemis/components/PrintArtemis.java      | 166 +++++++++++++++---
 4 files changed, 195 insertions(+), 43 deletions(-)
 mode change 100755 => 100644 art

diff --git a/art b/art
old mode 100755
new mode 100644
index 16cf2c2af..16f98d7dd
--- a/art
+++ b/art
@@ -6,8 +6,6 @@
 # necessary a symbolic link can be made to this script from
 # /usr/local/bin/ or elsewhere. 
 
-# $Header: //tmp/pathsoft/artemis/art,v 1.26 2009-09-21 15:45:47 tjc Exp $
-
 # resolve links - $0 may be a link
 PRG=$0
 progname=`basename $0`
@@ -30,6 +28,9 @@ LIBDIR=/nfs/pathsoft/prod/javalibs
 
 CLASSPATH=$ARTEMIS_HOME:$ARTEMIS_HOME/lib/biojava.jar:$ARTEMIS_HOME/lib/jemAlign.jar:$ARTEMIS_HOME/lib/jakarta-regexp-1.2.jar:$ARTEMIS_HOME/lib/macos.jar:$ARTEMIS_HOME/lib/postgresql-8.4-701.jdbc3.jar:$CLASSPATH
 
+# batik jars
+CLASSPATH=$CLASSPATH:$ARTEMIS_HOME/lib/batik/batik-awt-util.jar:$ARTEMIS_HOME/lib/batik/batik-dom.jar:$ARTEMIS_HOME/lib/batik/batik-ext.jar:$ARTEMIS_HOME/lib/batik/batik-svggen.jar:$ARTEMIS_HOME/lib/batik/batik-util.jar:$ARTEMIS_HOME/lib/batik/batik-xml.jar
+
 # j2ssh jars
 CLASSPATH=$CLASSPATH:$ARTEMIS_HOME/lib/j2ssh/commons-logging.jar:$ARTEMIS_HOME/lib/j2ssh/j2ssh-core.jar:$ARTEMIS_HOME/lib/j2ssh/
 
diff --git a/uk/ac/sanger/artemis/components/FeatureDisplay.java b/uk/ac/sanger/artemis/components/FeatureDisplay.java
index 8c279573a..bc6cb235c 100644
--- a/uk/ac/sanger/artemis/components/FeatureDisplay.java
+++ b/uk/ac/sanger/artemis/components/FeatureDisplay.java
@@ -68,6 +68,8 @@ import javax.swing.UIManager;
 import javax.swing.ImageIcon;
 import javax.swing.JFrame;
 
+import org.apache.batik.svggen.SVGGraphics2D;
+
 /**
  *  This component is used for displaying an Entry.
  *
@@ -1890,8 +1892,19 @@ public class FeatureDisplay extends EntryGroupPanel
 
     // draw fwd bases
     if(getScaleFactor() == 0)
-      g.drawString(forward_visible_bases, offset * getFontWidth(),
-                   yposition + getFontAscent() + 1);
+    {
+      if(!(g instanceof SVGGraphics2D))
+        g.drawString(forward_visible_bases, offset * getFontWidth(),
+            yposition + getFontAscent() + 1);
+      else
+      {
+        // for svg graphics
+        for(int i=0;i<forward_visible_bases.length();i++)
+          g.drawString(String.valueOf(forward_visible_bases.charAt(i)), 
+              (offset+i)*getFontWidth(), 
+              yposition + getFontAscent() + 1);
+      }
+    }
     else
     {
       for(int base_index = 0; base_index < forward_sequence_length;
@@ -1914,8 +1927,19 @@ public class FeatureDisplay extends EntryGroupPanel
 
     // draw bwd bases
     if(getScaleFactor() == 0)
-      g.drawString(reverse_visible_bases, offset * getFontWidth(),
-                   yposition + getFontAscent() + 1);
+    {  
+      if(!(g instanceof SVGGraphics2D))
+        g.drawString(reverse_visible_bases, offset * getFontWidth(),
+            yposition + getFontAscent() + 1);
+      else
+      {
+        // for svg graphics
+        for(int i=0;i<reverse_visible_bases.length();i++)
+          g.drawString(String.valueOf(reverse_visible_bases.charAt(i)), 
+              (offset+i)*getFontWidth(), 
+              yposition + getFontAscent() + 1);
+      }
+    }
     else
     {
       for(int base_index = 0; base_index < reverse_sequence_length;
@@ -2200,8 +2224,15 @@ public class FeatureDisplay extends EntryGroupPanel
     else
        draw_x_position = (int)((offset + frame_start + 1) * getScaleValue());
 
-    g.drawString(codons, draw_x_position,
+    if(!(g instanceof SVGGraphics2D))
+      g.drawString(codons, draw_x_position,
                  draw_y_position + getFontAscent() + 1);
+    else
+    {
+      for(int i=0;i<codons.length();i++)
+        g.drawString(String.valueOf(codons.charAt(i)), draw_x_position+(i*getFontWidth() ), 
+          draw_y_position + getFontAscent() + 1);
+    }
   }
 
   /**
diff --git a/uk/ac/sanger/artemis/components/Plot.java b/uk/ac/sanger/artemis/components/Plot.java
index 2063ea330..5a24f1de1 100644
--- a/uk/ac/sanger/artemis/components/Plot.java
+++ b/uk/ac/sanger/artemis/components/Plot.java
@@ -51,6 +51,8 @@ import javax.swing.JMenuItem;
 import javax.swing.JScrollBar;
 import javax.swing.JPopupMenu;
 
+import org.apache.batik.svggen.SVGGraphics2D;
+
 /**
  *  This class implements a simple plot component.
  *  @author Kim Rutherford
@@ -682,11 +684,17 @@ public abstract class Plot extends JPanel
     if(offscreen == null || lastPaintHeight != height)
       offscreen = createImage(width, height);
 
-    Graphics og = offscreen.getGraphics();
-    og.setClip(0, 0, width, height);
-    og.setColor(Color.WHITE);
-    og.fillRect(0, 0, width, height);
-
+    final Graphics og;
+    if(g instanceof SVGGraphics2D)
+      og = g;
+    else
+    {
+      og = offscreen.getGraphics();
+      og.setClip(0, 0, width, height);
+      og.setColor(Color.WHITE);
+      og.fillRect(0, 0, width, height);
+    }
+    
     // Redraw the graph on the canvas using the algorithm from the
     // constructor.
 
@@ -703,8 +711,12 @@ public abstract class Plot extends JPanel
     
     numPlots = drawMultiValueGraph(og,lines);
     drawLabels(og,numPlots);
-    g.drawImage(offscreen, 0, 0, null);
-    og.dispose();
+    
+    if( !(g instanceof SVGGraphics2D) )
+    {
+      g.drawImage(offscreen, 0, 0, null);
+      og.dispose();
+    }
     lastPaintHeight = height;
   }
 
diff --git a/uk/ac/sanger/artemis/components/PrintArtemis.java b/uk/ac/sanger/artemis/components/PrintArtemis.java
index f72fef4d4..4abd4784b 100644
--- a/uk/ac/sanger/artemis/components/PrintArtemis.java
+++ b/uk/ac/sanger/artemis/components/PrintArtemis.java
@@ -29,9 +29,24 @@ import java.awt.print.Printable;
 import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
 import java.awt.event.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
 import javax.swing.*;
-import java.io.*;
 
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGraphics2DIOException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import uk.ac.sanger.artemis.Options;
 import uk.ac.sanger.artemis.editor.ScrollPanel;
 
 /**
@@ -66,15 +81,45 @@ public class PrintArtemis extends ScrollPanel implements Printable
   }
 
   /**
-  *
   * Override paintComponent to draw entry
-  *
   */
-  public void paintComponent(Graphics g)
+  public void paintComponent(Graphics g2d)
   {
 // let UI delegate paint first (incl. background filling)
-    super.paintComponent(g);
-    Graphics2D g2d = (Graphics2D)g.create();
+    super.paintComponent(g2d);
+
+    // feature list
+    if(featListDisplay.isSelected())
+    {
+      FeatureList flist = entry.getFeatureList();
+      Point ploc = flist.getViewport().getViewPosition(); 
+      try
+      {
+        int translateX = 0;
+        if(selectDisplay.isSelected())
+          translateX += entry.getSelectionInfoDisplay().getHeight();
+        if(groupsDisplay.isSelected())
+          translateX += entry.getEntryGroupDisplay().getHeight();
+        if(plotsDisplay.isSelected())
+          translateX += entry.getBasePlotGroup().getHeight();
+        if(jamDisplay.isSelected() && entry.getBamPanel() != null && entry.getBamPanel().isVisible())
+          translateX += entry.getBamPanel().getHeight()-1;
+        if(vcfDisplay.isSelected() && entry.getVcfView() != null && entry.getVcfView().isVisible())
+          translateX += entry.getVcfPanel().getHeight();
+        if(onelineDisplay.isSelected())
+          translateX += entry.getOneLinePerEntryDisplay().getHeight();
+        if(featDisplay.isSelected())
+          translateX += entry.getFeatureDisplay().getHeight();
+        if(baseDisplay.isSelected())
+          translateX += entry.getBaseDisplay().getHeight();
+
+        translateX-=2+ploc.y;
+        g2d.translate(0,translateX);
+        flist.paintComponent(g2d);
+        g2d.translate(0,-translateX);
+      }
+      catch(IllegalArgumentException e){} // thrown if the list is not visible
+    }
 
     // selection info
     if(selectDisplay.isSelected())
@@ -128,24 +173,9 @@ public class PrintArtemis extends ScrollPanel implements Printable
       entry.getBaseDisplay().paintComponent(g2d);
       g2d.translate(0,entry.getBaseDisplay().getHeight());
     }
-
-    // feature list
-    if(featListDisplay.isSelected())
-    {
-      FeatureList flist = entry.getFeatureList();
-      Point ploc = flist.getViewport().getViewPosition(); 
-      try
-      {
-        BufferedImage offScreen = new BufferedImage(flist.getViewport().getWidth(), 
-          flist.getViewport().getHeight(), BufferedImage.TYPE_INT_RGB);
-        Graphics og = offScreen.getGraphics();
-        og.translate(0,-ploc.y);
-        flist.paintComponent(og);
-        g2d.drawImage(offScreen, 0, 0, null);
-      }
-      catch(IllegalArgumentException e){} // thrown if the list is not visible
-    }
   }
+  
+  
 
 
   /**
@@ -153,7 +183,7 @@ public class PrintArtemis extends ScrollPanel implements Printable
   * Set the size of the image
   *
   */
-  private void setImageSize()
+  private Dimension getImageSize()
   {
     height = 0;
     width  = entry.getFeatureDisplay().getDisplayWidth();
@@ -185,9 +215,14 @@ public class PrintArtemis extends ScrollPanel implements Printable
 
     if(featListDisplay.isSelected())
       height += entry.getFeatureList().getViewport().getExtentSize().height;
-    setPreferredSize(new Dimension(width,height));
+    return new Dimension(width,height);
   }
 
+  private void setImageSize()
+  {
+    setPreferredSize(getImageSize());
+  }
+  
   /**
   *
   * Display a print preview page
@@ -391,6 +426,15 @@ public class PrintArtemis extends ScrollPanel implements Printable
     f.setVisible(true);
   }
 
+  private String[] getImageFormats()
+  {
+    final String fmts[] = javax.imageio.ImageIO.getWriterFormatNames();
+    final String tmpFmts[] = new String[fmts.length+1];
+    System.arraycopy(fmts, 0, tmpFmts, 0, fmts.length);
+    tmpFmts[tmpFmts.length-1] = "svg";
+    return tmpFmts;
+  }
+  
   /**
   *
   * Print to a jpeg or png file
@@ -399,7 +443,7 @@ public class PrintArtemis extends ScrollPanel implements Printable
   public void print()
   {
     // file chooser
-    StickyFileChooser fc = new StickyFileChooser();
+    final StickyFileChooser fc = new StickyFileChooser();
     File fselect = new File(fc.getCurrentDirectory()+
                             System.getProperty("file.separator")+
                             "artemis.png");
@@ -413,9 +457,27 @@ public class PrintArtemis extends ScrollPanel implements Printable
     YBox.add(labFormat);
 
     Box bacross = Box.createHorizontalBox();
-    JComboBox formatSelect =
-       new JComboBox(javax.imageio.ImageIO.getWriterFormatNames());
+    final JComboBox formatSelect = new JComboBox(getImageFormats());
     formatSelect.setSelectedItem("png");
+    formatSelect.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent arg0)
+      {
+        String selected;
+        if(fc.getSelectedFile() != null)
+        {
+          selected = fc.getSelectedFile().getAbsolutePath();
+          String fmts[] = getImageFormats();
+          for(int i=0; i<fmts.length; i++)
+            selected = selected.replaceAll("."+fmts[i]+"$", "");
+        }
+        else
+          selected = "artemis";
+        
+        fc.setSelectedFile(new File(selected+"."+
+               formatSelect.getSelectedItem()));
+      }
+    });
 
     Dimension d = formatSelect.getPreferredSize();
     formatSelect.setMaximumSize(d);
@@ -488,6 +550,13 @@ public class PrintArtemis extends ScrollPanel implements Printable
 
     // remove file extension
     String fsave = fc.getSelectedFile().getAbsolutePath().toLowerCase();
+    
+    if(fsave.endsWith(".svg"))
+    {
+      createSVG(fc.getSelectedFile());
+      return;
+    }
+
     if(fsave.endsWith(".png") ||
        fsave.endsWith(".jpg") ||
        fsave.endsWith(".jpeg") )
@@ -514,6 +583,45 @@ public class PrintArtemis extends ScrollPanel implements Printable
     }
   }
   
+  private void createSVG(final File fout)
+  {
+    final DOMImplementation domImpl =
+        GenericDOMImplementation.getDOMImplementation();
+    final Document doc = domImpl.createDocument(
+        "http://www.w3.org/2000/svg", "svg", null);
+
+    SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(doc);
+    ctx.setComment("Generated by Artemis with Batik SVG Generator");
+    final SVGGraphics2D svgG = new SVGGraphics2D(ctx, true);
+    svgG.setFont(Options.getOptions().getFont());
+    final FontMetrics fm = svgG.getFontMetrics();
+    final Dimension d = getImageSize();
+    svgG.setSVGCanvasSize( new Dimension(
+        d.width+fm.stringWidth(" "), d.height+fm.getHeight()) );
+    paintComponent(svgG);
+
+    try
+    {
+      final Writer out = new OutputStreamWriter(
+          new FileOutputStream(fout), "UTF-8");
+      svgG.stream(out, true);
+    }
+    catch (UnsupportedEncodingException e)
+    {
+      e.printStackTrace();
+    }
+    catch (SVGGraphics2DIOException e)
+    {
+      e.printStackTrace();
+    }
+    catch (FileNotFoundException e)
+    {
+      e.printStackTrace();
+    }
+
+    return;
+  }
+  
   protected void doPrintActions()
   {
     final PrinterJob pj=PrinterJob.getPrinterJob();
@@ -575,7 +683,7 @@ public class PrintArtemis extends ScrollPanel implements Printable
   public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException
   {
     setImageSize();
-    Graphics2D g2 = (Graphics2D) g;
+    Graphics2D g2 = (Graphics2D)g.create();
 
 //  RepaintManager.currentManager(this).setDoubleBufferingEnabled(false);
     Dimension d = this.getSize();    //get size of document
-- 
GitLab