/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.ui.svg; import org.broad.igv.ui.color.ColorUtilities; import javax.swing.*; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ImageObserver; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import java.io.PrintWriter; import java.text.AttributedCharacterIterator; import java.util.Map; /** * This is an experimental class, its not actually used (yet) * * @date Nov 20, 2010 */ public class SVGGraphics extends Graphics2D { PrintWriter outputStream; Color color = Color.black; Color background = Color.white; BasicStroke stroke; Font font; FontRenderContext fontRenderContext; FontMetrics fontMetrics; AffineTransform transform; JComponent component; // <= dummy component to obtain font metrics int translateX; int translateY; String clipRef; static int clipNumber = 0; Shape clip; public SVGGraphics(PrintWriter outputStream, Rectangle clip) { this.clip = clip; initDefaults(); this.outputStream = outputStream; } public SVGGraphics(SVGGraphics g) { this.clip = g.clip; this.outputStream = g.outputStream; this.color = g.color; this.background = g.background; this.stroke = g.stroke; this.font = g.font; this.fontMetrics = g.fontMetrics; this.fontRenderContext = g.fontRenderContext; this.component = g.component; if (g.transform != null) { this.transform = new AffineTransform(g.transform); } this.clipRef = g.clipRef; this.translateX = g.translateX; this.translateY = g.translateY; } private void initDefaults() { component = new JPanel(); stroke = new BasicStroke(); color = Color.black; font = new Font("Arial", Font.PLAIN, 12); fontMetrics = component.getFontMetrics(font); fontRenderContext = new FontRenderContext(null, true, false); translateX = 0; translateY = 0; } @Override public void drawString(String s, int x, int y) { int tx = translateX + x; int ty = translateY + y; outputStream.print("<text x=\""); outputStream.print(tx); outputStream.print("\" y=\""); outputStream.print(ty); outputStream.println("\""); outputStream.print(" style=\"font-family: " + font.getName() + ";"); outputStream.print(" font-size:" + font.getSize() + ";"); if (font.isBold()) { outputStream.print(" font-weight: bold;"); } outputStream.print(" fill:rgb" + getRGBString()); if (clipRef != null) { outputStream.print(";clip-path: " + clipRef); } outputStream.print("\" "); applyTransform(); outputStream.print(">"); outputStream.print(s); outputStream.println("</text>"); } @Override public void setStroke(Stroke stroke) { if (!(stroke instanceof BasicStroke)) { // throw exception } this.stroke = (BasicStroke) stroke; } @Override public Graphics create() { return new SVGGraphics(this); } @Override public void translate(int x, int y) { translateX += x; translateY += y; } @Override public void setClip(int x, int y, int w, int h) { clip = new Rectangle(x, y, w, h); int tx = translateX + x; int ty = translateY + y; String id = getClipId(); outputStream.println("<clipPath id=\"" + id + "\">\n" + " <rect id=\"rect1\" x=\"" + tx + "\" y=\"" + ty + "\"\n" + " width=\"" + w + "\" height=\"" + h + "\"/>"); outputStream.println("</clipPath>"); clipRef = "url(#" + id + ")"; } private static synchronized String getClipId() { return "clip_" + clipNumber++; } @Override public void drawLine(int x1, int y1, int x2, int y2) { int tx1 = translateX + x1; int ty1 = translateY + y1; int tx2 = translateX + x2; int ty2 = translateY + y2; String rgbString = getRGBString(); float strokeWidth = stroke.getLineWidth(); outputStream.println("<line x1=\"" + tx1 + "\" y1=\"" + ty1 + "\" x2=\"" + tx2 + "\" y2=\"" + ty2 + "\""); outputStream.print("style=\"stroke:rgb" + rgbString + ";stroke-width:" + strokeWidth); if (clipRef != null) { outputStream.print(";clip-path: " + clipRef); } applyTransform(); outputStream.println("\"/>"); } @Override public void drawRect(int x, int y, int w, int h) { int tx = translateX + x; int ty = translateY + y; String rgbString = getRGBString(); float strokeWidth = stroke.getLineWidth(); outputStream.print("<rect x=\""); outputStream.print(tx); outputStream.print("\" y=\""); outputStream.print(ty); outputStream.print("\" width=\""); outputStream.print(w); outputStream.print("\" height=\""); outputStream.print(h); outputStream.println("\""); outputStream.print(" style=\"fill:none;stroke-width:" + strokeWidth + ";stroke:rgb" + rgbString); if (clipRef != null) { outputStream.print(";clip-path: " + clipRef); } applyTransform(); outputStream.println("\"/>"); } @Override public void fillRect(int x, int y, int w, int h) { int tx = translateX + x; int ty = translateY + y; String rgbString = getRGBString(); float strokeWidth = stroke.getLineWidth(); outputStream.print("<rect x=\""); outputStream.print(tx); outputStream.print("\" y=\""); outputStream.print(ty); outputStream.print("\" width=\""); outputStream.print(w); outputStream.print("\" height=\""); outputStream.print(h); outputStream.println("\""); outputStream.print(" style=\"fill:rgb" + rgbString); if (clipRef != null) { outputStream.print(";clip-path: " + clipRef); } applyTransform(); outputStream.println("\"/>"); } @Override public void drawPolygon(int[] x, int[] y, int npts) { String rgbString = getRGBString(); float strokeWidth = stroke.getLineWidth(); outputStream.print("<polygon points=\""); for (int i = 0; i < npts; i++) { int tx = translateX + x[i]; int ty = translateY + y[i]; outputStream.print(tx); outputStream.print(","); outputStream.print(ty); outputStream.print(" "); } outputStream.println("\""); outputStream.print(" style=\"fill:none;stroke-width:" + strokeWidth + ";stroke:rgb" + rgbString); if (clipRef != null) { outputStream.print(";clip-path: " + clipRef); } applyTransform(); outputStream.println("\"/>"); } @Override public void fillPolygon(int[] x, int[] y, int npts) { String rgbString = getRGBString(); float strokeWidth = stroke.getLineWidth(); outputStream.print("<polygon points=\""); for (int i = 0; i < npts; i++) { int tx = translateX + x[i]; int ty = translateY + y[i]; outputStream.print(tx); outputStream.print(","); outputStream.print(ty); outputStream.print(" "); } outputStream.println("\""); outputStream.print(" style=\"fill:rgb" + rgbString); if (clipRef != null) { outputStream.print(";clip-path: " + clipRef); } applyTransform(); outputStream.println("\"/>"); } @Override public void clearRect(int x, int y, int w, int h) { Color c = color; try { color = background; fillRect(x, y, w, h); } finally { color = c; } } @Override public void transform(AffineTransform affineTransform) { if (transform == null) { setTransform(affineTransform); } else { transform.concatenate(affineTransform); } } private void applyTransform() { if (transform != null) { // TODO -- cache the matrix double[] matrix = new double[6]; transform.getMatrix(matrix); outputStream.print(" transform=\"matrix("); for (int i = 0; i < matrix.length; i++) { outputStream.print(matrix[i]); if (i < matrix.length - 1) outputStream.print(" "); } outputStream.println(")\" "); } } private String getRGBString() { String rgbString = ColorUtilities.colorToString(color); return "(" + rgbString + ")"; } @Override public Shape getClip() { return clip; //To change body of implemented methods use File | Settings | File Templates. } @Override public void setClip(Shape shape) { this.clip = shape; } @Override public void setTransform(AffineTransform affineTransform) { this.transform = affineTransform; } @Override public FontMetrics getFontMetrics() { return fontMetrics; } @Override public FontMetrics getFontMetrics(Font font) { return component.getFontMetrics(font); } @Override public Rectangle getClipBounds() { return clip.getBounds(); } @Override public void clipRect(int x, int y, int w, int h) { setClip(x, y, w, h); } @Override public void translate(double x, double y) { System.out.println("Translate " + x + " " + y); } @Override public Color getColor() { return color; //To change body of implemented methods use File | Settings | File Templates. } @Override public void setColor(Color color) { this.color = color; } @Override public Font getFont() { return font; } @Override public void setFont(Font font) { this.font = font; fontMetrics = component.getFontMetrics(font); } @Override public void setPaintMode() { //To change body of implemented methods use File | Settings | File Templates. } @Override public void setXORMode(Color color) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void copyArea(int i, int i1, int i2, int i3, int i4, int i5) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawRoundRect(int i, int i1, int i2, int i3, int i4, int i5) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void fillRoundRect(int i, int i1, int i2, int i3, int i4, int i5) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawOval(int i, int i1, int i2, int i3) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void fillOval(int i, int i1, int i2, int i3) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawArc(int i, int i1, int i2, int i3, int i4, int i5) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void fillArc(int i, int i1, int i2, int i3, int i4, int i5) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawPolyline(int[] ints, int[] ints1, int i) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void rotate(double v) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void rotate(double v, double v1, double v2) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void scale(double v, double v1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void shear(double v, double v1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void setRenderingHint(RenderingHints.Key key, Object o) { //To change body of implemented methods use File | Settings | File Templates. } @Override public Object getRenderingHint(RenderingHints.Key key) { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public void setRenderingHints(Map<?, ?> map) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void addRenderingHints(Map<?, ?> map) { //To change body of implemented methods use File | Settings | File Templates. } @Override public RenderingHints getRenderingHints() { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public void draw(Shape shape) { //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, AffineTransform affineTransform, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawImage(BufferedImage bufferedImage, BufferedImageOp bufferedImageOp, int i, int i1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawRenderedImage(RenderedImage renderedImage, AffineTransform affineTransform) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawRenderableImage(RenderableImage renderableImage, AffineTransform affineTransform) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawString(String s, float v, float v1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawString(AttributedCharacterIterator attributedCharacterIterator, int i, int i1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, int i, int i1, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, int i, int i1, int i2, int i3, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, int i, int i1, Color color, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, int i, int i1, int i2, int i3, Color color, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean drawImage(Image image, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7, Color color, ImageObserver imageObserver) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public void dispose() { } @Override public void drawString(AttributedCharacterIterator attributedCharacterIterator, float v, float v1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void drawGlyphVector(GlyphVector glyphVector, float v, float v1) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void fill(Shape shape) { //To change body of implemented methods use File | Settings | File Templates. } @Override public boolean hit(Rectangle rectangle, Shape shape, boolean b) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public GraphicsConfiguration getDeviceConfiguration() { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public void setComposite(Composite composite) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void setPaint(Paint paint) { //To change body of implemented methods use File | Settings | File Templates. } @Override public AffineTransform getTransform() { return transform; } @Override public Paint getPaint() { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public Composite getComposite() { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public void setBackground(Color color) { this.background = color; } @Override public Color getBackground() { return background; //To change body of implemented methods use File | Settings | File Templates. } @Override public Stroke getStroke() { return stroke; //To change body of implemented methods use File | Settings | File Templates. } @Override public void clip(Shape shape) { //To change body of implemented methods use File | Settings | File Templates. } @Override public FontRenderContext getFontRenderContext() { return fontRenderContext; //To change body of implemented methods use File | Settings | File Templates. } }