1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.utgenome.graphics;
26
27 import java.awt.Color;
28 import java.awt.Font;
29 import java.awt.FontMetrics;
30 import java.awt.Graphics2D;
31 import java.awt.RenderingHints;
32 import java.awt.geom.Rectangle2D;
33 import java.awt.image.BufferedImage;
34 import java.io.IOException;
35 import java.util.ArrayList;
36
37 import javax.imageio.ImageIO;
38 import javax.servlet.http.HttpServletResponse;
39
40 import org.xerial.util.log.Logger;
41
42
43
44
45
46
47
48 public class GenomeCanvas {
49
50 private static Logger _logger = Logger.getLogger(GenomeCanvas.class);
51
52 private final GenomeWindow window;
53 private BufferedImage image;
54 private Graphics2D g;
55 private int canvasWidth;
56 private int canvasHeight;
57
58 private int yOffset = 0;
59
60 private boolean isReverse = false;
61
62 private ArrayList<Integer> lastGeneEnds = new ArrayList<Integer>();
63
64 private int geneHeight = 5;
65
66 public void setGeneHeight(int height) {
67 this.geneHeight = height;
68 }
69
70 public Graphics2D getGraphics() {
71 return g;
72 }
73
74 public GenomeWindow getGenomeWindow() {
75 return window;
76 }
77
78 public GenomeCanvas(int width, int height, GenomeWindow window) {
79 this.window = window;
80 setPixelSize(width, height);
81
82 isReverse = window.getReverse();
83 if (!isReverse)
84 this.lastGeneEnds.add(Integer.MIN_VALUE);
85 else
86 this.lastGeneEnds.add(Integer.MAX_VALUE);
87 }
88
89 public int getWidth() {
90 return canvasWidth;
91 }
92
93 public BufferedImage getBufferedImage() {
94 return image;
95 }
96
97 public void drawTag(long startIndexOnGenome, long endIndexOnGenome) {
98 drawTag(startIndexOnGenome, endIndexOnGenome, Color.GRAY);
99 }
100
101 public void drawTag(long startIndexOnGenome, long endIndexOnGenome, Color color) {
102 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
103 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
104
105 if (start > end) {
106 int temp = start;
107 start = end;
108 end = temp;
109 }
110
111 int width = end - start;
112 if (width <= 0)
113 width = 1;
114
115 drawRect(start, yOffset, width, geneHeight - 1, color);
116 yOffset += geneHeight;
117 if (yOffset > canvasHeight)
118 yOffset = 0;
119 }
120
121 public void drawGeneRect(long startIndexOnGenome, long endIndexOnGenome, int yOffset, int height, Color color) {
122 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
123 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
124
125 if (start > end) {
126 int temp = start;
127 start = end;
128 end = temp;
129 }
130
131 int width = end - start;
132 if (width <= 0)
133 width = 1;
134
135 if (start <= canvasWidth && end >= 0)
136 drawRect(start, yOffset, width, height, color);
137 }
138
139 public void drawRect(int x, int y, int width, int height, Color color) {
140 Rectangle2D rect = new Rectangle2D.Double(x, y, width, height);
141 g.setColor(color);
142 g.fill(rect);
143 }
144
145 public void drawBase(String text, long startIndexOnGenome, long endIndexOnGenome, int yOffset, float fontSize, Color color) {
146 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
147 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
148 int drawStart;
149
150 Font f = new Font("SansSerif", Font.PLAIN, 1);
151 f = f.deriveFont(fontSize);
152 g.setFont(f);
153
154 FontMetrics fontMetrics = g.getFontMetrics();
155 int fontWidth = fontMetrics.stringWidth(text);
156
157 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
158 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
159 g.setColor(color);
160
161 if (isReverse) {
162 int temp = start;
163 start = end;
164 end = temp;
165 }
166
167 drawStart = (int) (start + (end - start) / 2.0f - fontWidth / 2.0f);
168 if (drawStart < 0)
169 drawStart = end;
170
171 g.drawString(text, drawStart, yOffset);
172
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187 public void drawText(String text, long startIndexOnGenome, long endIndexOnGenome, int yOffset, float fontSize, Color color) {
188 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
189 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
190 int drawStart;
191
192 Font f = new Font("Arial", Font.PLAIN, 1);
193 f = f.deriveFont(fontSize);
194 g.setFont(f);
195
196 FontMetrics fontMetrics = g.getFontMetrics();
197 int fontWidth = fontMetrics.stringWidth(text);
198
199
200
201 g.setColor(color);
202
203 if (isReverse) {
204 int temp = start;
205 start = end;
206 end = temp;
207 }
208
209 drawStart = (int) (start + (end - start) / 2.0f - fontWidth / 2.0f);
210 if (drawStart < 0)
211 drawStart = end;
212
213 g.drawString(text, drawStart, yOffset);
214 }
215
216 public void drawText(String text, long startIndexOnGenome, long endIndexOnGenome, int yOffset, int fontSize, Color color) {
217 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
218 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
219 int drawStart;
220
221 g.setFont(new Font("Arial", Font.PLAIN, fontSize));
222 FontMetrics fontMetrics = g.getFontMetrics();
223 int fontWidth = fontMetrics.stringWidth(text) + 2;
224 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
225 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
226
227 g.setColor(color);
228
229 if (isReverse) {
230 int temp = start;
231 start = end;
232 end = temp;
233 }
234 drawStart = start - fontWidth;
235 if (drawStart < 0)
236 drawStart = end + 2;
237
238 g.drawString(text, drawStart, yOffset + (int) (fontSize * 0.85));
239 }
240
241 public void drawLocusLabel(String text, long startIndexOnGenome, long endIndexOnGenome, int yOffset, float fontSize, Color color) {
242 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
243 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
244
245 int drawStart;
246
247 Font f = new Font("Arial", Font.PLAIN, 1);
248 f = f.deriveFont(fontSize);
249 g.setFont(f);
250
251 FontMetrics fontMetrics = g.getFontMetrics();
252 int fontWidth = fontMetrics.stringWidth(text);
253
254
255
256 g.setColor(color);
257
258 if (isReverse) {
259 int temp = start;
260 start = end;
261 end = temp;
262 }
263
264 drawStart = (start - fontWidth) - 1;
265
266 g.drawString(text, drawStart, yOffset);
267 }
268
269 public void outputImage(HttpServletResponse response, final String imageType) throws IOException {
270 response.setContentType("image/" + imageType);
271 ImageIO.write(image, imageType, response.getOutputStream());
272 }
273
274 public void setPixelSize(int width, int height) {
275 canvasWidth = width;
276 canvasHeight = height;
277
278 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
279 g = image.createGraphics();
280
281 }
282
283 public void drawLine(long x1, long y1, long x2, long y2, Color lineColor) {
284 g.setColor(lineColor);
285 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
286 g.drawLine((int) (window.getXPosOnWindow(x1, canvasWidth) + 0.5f), (int) y1, (int) (window.getXPosOnWindow(x2, canvasWidth) - 0.5f), (int) y2);
287 }
288
289 public void setPixelHeight(int height) {
290
291 canvasHeight = height;
292
293 image = new BufferedImage(canvasWidth, height, BufferedImage.TYPE_INT_ARGB);
294 g = image.createGraphics();
295
296 }
297
298 public int getFontWidth(String text) {
299 FontMetrics metrics = g.getFontMetrics(g.getFont());
300 return metrics.stringWidth(text);
301 }
302
303 public int getXPosOnWindow(long indexOnGenome) {
304 return window.getXPosOnWindow(indexOnGenome, canvasWidth);
305 }
306
307 public int getOffset(String text, int fontSize, long startIndexOnGenome, long endIndexOnGenome, int gapWidth) {
308 int offset = 0;
309 boolean isSpace = false;
310
311 int start = window.getXPosOnWindow(startIndexOnGenome, canvasWidth);
312 int end = window.getXPosOnWindow(endIndexOnGenome, canvasWidth);
313 if (isReverse) {
314 int temp = start;
315 start = end;
316 end = temp;
317 }
318
319 g.setFont(new Font("SansSerif", Font.PLAIN, fontSize));
320 FontMetrics fontMetrics = g.getFontMetrics();
321 int textWidth = fontMetrics.stringWidth(text);
322
323
324 if (!isReverse) {
325 for (int i = 0; i < lastGeneEnds.size(); i++) {
326 if (start - textWidth <= lastGeneEnds.get(i).intValue()) {
327 offset++;
328 }
329 else {
330 lastGeneEnds.set(i, Integer.valueOf(getEndIndex(text, fontSize, start, end, gapWidth)));
331 isSpace = true;
332 break;
333 }
334 }
335 if (!isSpace) {
336 lastGeneEnds.add(getEndIndex(text, fontSize, start, end, gapWidth));
337 }
338 }
339 else {
340 for (int i = 0; i < lastGeneEnds.size(); i++) {
341 if (getEndIndex(text, fontSize, start, end, gapWidth) >= lastGeneEnds.get(i).intValue()) {
342 offset++;
343 }
344 else {
345 lastGeneEnds.set(i, Integer.valueOf(start - textWidth));
346 isSpace = true;
347 break;
348 }
349 }
350 if (!isSpace) {
351 lastGeneEnds.add(start - textWidth);
352 }
353 }
354
355 return offset;
356 }
357
358 public int getEndIndex(String text, int fontSize, int start, int end, int gapWidth) {
359 String tempText = "a";
360
361 g.setFont(new Font("SansSerif", Font.PLAIN, fontSize));
362 FontMetrics fontMetrics = g.getFontMetrics();
363
364 int fontWidth = fontMetrics.stringWidth(text);
365 int tempWidth = fontMetrics.stringWidth(tempText);
366
367 if (start - fontWidth < 0) {
368 fontWidth += tempWidth * gapWidth;
369 }
370 else {
371 fontWidth = tempWidth * gapWidth;
372 }
373 return end + fontWidth;
374 }
375 }