001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.bio.gui.sequence; 022 023import java.awt.Font; 024import java.awt.geom.Point2D; 025 026import org.biojava.bio.seq.FeatureHolder; 027import org.biojava.bio.seq.Sequence; 028import org.biojava.bio.symbol.RangeLocation; 029import org.biojava.bio.symbol.SymbolList; 030 031/** 032 * <p> 033 * A stand-alone SequenceRenderContext to make it easy to render to an image. 034 * </p> 035 * 036 * <p> 037 * This class makes it very easy to render sequence information into an 038 * arbitrary graphics object without the need to fuss about with AWT or 039 * Swing components. You chose the width of the image and the region of the 040 * sequence to render. It will calculate the scale factor to ensure that the 041 * whole region of the sequence fits into that width. You can then use the 042 * context to render any number of SequenceRenderer instances to any Graphics2D 043 * instance you want, for example, to an image that's to be written out by a 044 * servlet. 045 * </p> 046 * 047 * <h2>Example</h2> 048 * 049 * <pre> 050 * HeadlessRenderContext ctxt = new HeadlessRenderContext( 051 * seq, // the sequence to render 052 * range, // a RangeLocation giving the block you want to render 053 * width // an int specifying the image width in pixles 054 * ); 055 * 056 * BufferedImage img = new BufferedImage( 057 * width, // image width 058 * (int) Math.ceil(seqRend.getDepth(ctxt), // calculated height 059 * BufferedImage.TYPE_INT_RGB // let's use RGB 060 * ); 061 * 062 * // set stuff up 063 * Graphics2D graph = img.createGraphics(); 064 * graph.setPaint(Color.WHITE); 065 * graph.fillRect(0, 0, img.getWidth(), img.getHeight()); 066 * 067 * // and now render the sequences 068 * sequenceRenderer.paint(graph, ctxt); 069 * 070 * // let's dump this out as a png 071 * ImageIO.write(image, "png", myFile); 072 * </pre> 073 * 074 * @since 1.3 075 * @author Matthew Pocock 076 */ 077 078public class HeadlessRenderContext 079implements SequenceRenderContext { 080 private static final Font FONT = new Font(null, Font.PLAIN, 10); 081 082 private final RangeLocation range; 083 private final double scale; 084 private final Sequence seq; 085 private final double offset; 086 087 public HeadlessRenderContext(Sequence seq, RangeLocation range, int width) { 088 this.seq = seq; 089 this.range = range; 090 this.scale = (double) width / 091 (double) (range.getMax() - range.getMin() + 1); 092 offset = -( (double) range.getMin() * scale); 093 } 094 095 public int getDirection() { 096 return HORIZONTAL; 097 } 098 099 public FeatureHolder getFeatures() { 100 return seq; 101 } 102 103 public Font getFont() { 104 return FONT; 105 } 106 107 public SequenceRenderContext.Border getLeadingBorder() { 108 return new SequenceRenderContext.Border(); 109 } 110 111 public RangeLocation getRange() { 112 return range; 113 } 114 115 public double getScale() { 116 return scale; 117 } 118 119 public SymbolList getSymbols() { 120 return seq; 121 } 122 123 public SequenceRenderContext.Border getTrailingBorder() { 124 return new SequenceRenderContext.Border(); 125 } 126 127 public double sequenceToGraphics(int i) { 128 return ((double) (i - 1)) * scale + offset; 129 } 130 131 public int graphicsToSequence(Point2D point) { 132 return graphicsToSequence(point.getX()); 133 } 134 135 public int graphicsToSequence(double d) { 136 return ((int) ((d - offset) / scale)) + 1; 137 } 138}