1 package jalview.renderer;
3 import jalview.analysis.AAFrequency;
4 import jalview.analysis.StructureFrequency;
5 import jalview.api.AlignViewportI;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.Annotation;
8 import jalview.datamodel.ColumnSelection;
9 import jalview.schemes.ColourSchemeI;
11 import java.awt.BasicStroke;
12 import java.awt.Color;
14 import java.awt.FontMetrics;
15 import java.awt.Graphics;
16 import java.awt.Graphics2D;
17 import java.awt.Image;
18 import java.awt.font.LineMetrics;
19 import java.awt.geom.AffineTransform;
20 import java.awt.image.ImageObserver;
21 import java.util.Hashtable;
23 import com.stevesoft.pat.Regex;
25 public class AnnotationRenderer
28 public AnnotationRenderer()
30 // TODO Auto-generated constructor stub
33 public void drawStemAnnot(Graphics g, Annotation[] row_annotations,
34 int lastSSX, int x, int y, int iconOffset, int startRes,
35 int column, boolean validRes, boolean validEnd)
38 g.setColor(STEM_COLOUR);
39 int sCol = (lastSSX / charWidth) + startRes;
41 int x2 = (x * charWidth);
42 Regex closeparen = new Regex("(\\))");
44 String dc = (column == 0 || row_annotations[column - 1] == null) ? ""
45 : row_annotations[column - 1].displayCharacter;
47 boolean diffupstream = sCol == 0 || row_annotations[sCol - 1] == null
48 || !dc.equals(row_annotations[sCol - 1].displayCharacter);
49 boolean diffdownstream = !validRes || !validEnd
50 || row_annotations[column] == null
51 || !dc.equals(row_annotations[column].displayCharacter);
52 // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
53 // If a closing base pair half of the stem, display a backward arrow
54 if (column > 0 && closeparen.search(dc))
58 // if (validRes && column>1 && row_annotations[column-2]!=null &&
59 // dc.equals(row_annotations[column-2].displayCharacter))
61 g.fillPolygon(new int[]
62 { lastSSX + 5, lastSSX + 5, lastSSX }, new int[]
63 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
74 // display a forward arrow
77 g.fillPolygon(new int[]
78 { x2 - 5, x2 - 5, x2 }, new int[]
79 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
88 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 7);
91 private int charWidth, endRes, charHeight;
93 private boolean validCharWidth, hasHiddenColumns;
95 private FontMetrics fm;
97 private final boolean MAC = new jalview.util.Platform().isAMac();
99 boolean av_renderHistogram = true, av_renderProfile = true,
100 av_normaliseProfile = false;
102 ColourSchemeI profcolour = null;
104 private ColumnSelection columnSelection;
106 private Hashtable[] hconsensus;
108 private Hashtable[] hStrucConsensus;
110 private boolean av_ignoreGapsConsensus;
113 * attributes set from AwtRenderPanelI
116 * old image used when data is currently being calculated and cannot be
119 private Image fadedImage;
122 * panel being rendered into
124 private ImageObserver annotationPanel;
127 * width of image to render in panel
129 private int imgWidth;
132 public void drawNotCanonicalAnnot(Graphics g, Annotation[] row_annotations,
133 int lastSSX, int x, int y, int iconOffset, int startRes,
134 int column, boolean validRes, boolean validEnd)
137 g.setColor(NOTCANONICAL_COLOUR);
138 int sCol = (lastSSX / charWidth) + startRes;
140 int x2 = (x * charWidth);
141 Regex closeparen = new Regex("(}|]|a|b|c|d)");
143 String dc = (column == 0 || row_annotations[column - 1] == null) ? ""
144 : row_annotations[column - 1].displayCharacter;
146 boolean diffupstream = sCol == 0 || row_annotations[sCol - 1] == null
147 || !dc.equals(row_annotations[sCol - 1].displayCharacter);
148 boolean diffdownstream = !validRes || !validEnd
149 || row_annotations[column] == null
150 || !dc.equals(row_annotations[column].displayCharacter);
151 // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
152 // If a closing base pair half of the stem, display a backward arrow
153 if (column > 0 && closeparen.search(dc))// closeletter_b.search(dc)||closeletter_c.search(dc)||closeletter_d.search(dc)||closecrochet.search(dc)) )
157 // if (validRes && column>1 && row_annotations[column-2]!=null &&
158 // dc.equals(row_annotations[column-2].displayCharacter))
160 g.fillPolygon(new int[]
161 { lastSSX + 5, lastSSX + 5, lastSSX }, new int[]
162 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
173 // display a forward arrow
176 g.fillPolygon(new int[]
177 { x2 - 5, x2 - 5, x2 }, new int[]
178 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
187 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 7);
189 // public void updateFromAnnotationPanel(FontMetrics annotFM, AlignViewportI
191 public void updateFromAwtRenderPanel(AwtRenderPanelI annotPanel,
194 fm = annotPanel.getFontMetrics();
195 annotationPanel = annotPanel;
196 fadedImage = annotPanel.getFadedImage();
197 imgWidth = annotPanel.getFadedImageWidth();
198 updateFromAlignViewport(av);
201 public void updateFromAlignViewport(AlignViewportI av)
203 charWidth = av.getCharWidth();
204 endRes = av.getEndRes();
205 charHeight = av.getCharHeight();
206 hasHiddenColumns = av.hasHiddenColumns();
207 validCharWidth = av.isValidCharWidth();
208 av_renderHistogram = av.isShowConsensusHistogram();
209 av_renderProfile = av.isShowSequenceLogo();
210 av_normaliseProfile = av.isNormaliseSequenceLogo();
211 profcolour = av.getGlobalColourScheme();
212 if (profcolour == null)
214 // Set the default colour for sequence logo if the alignnent has no
216 profcolour = av.getAlignment().isNucleotide() ? new jalview.schemes.NucleotideColourScheme()
217 : new jalview.schemes.ZappoColourScheme();
219 columnSelection = av.getColumnSelection();
220 hconsensus = av.getSequenceConsensusHash();// hconsensus;
221 hStrucConsensus = av.getRnaStructureConsensusHash(); // hStrucConsensus;
222 av_ignoreGapsConsensus = av.getIgnoreGapsConsensus();
225 public int[] getProfileFor(AlignmentAnnotation aa, int column)
227 // TODO : consider refactoring the global alignment calculation
228 // properties/rendering attributes as a global 'alignment group' which holds
229 // all vis settings for the alignment as a whole rather than a subset
231 if (aa.autoCalculated && aa.label.startsWith("Consensus"))
233 if (aa.groupRef != null && aa.groupRef.consensusData != null
234 && aa.groupRef.isShowSequenceLogo())
236 return AAFrequency.extractProfile(
237 aa.groupRef.consensusData[column],
238 aa.groupRef.getIgnoreGapsConsensus());
240 // TODO extend annotation row to enable dynamic and static profile data to
242 if (aa.groupRef == null && aa.sequenceRef == null && av_renderProfile)
244 return AAFrequency.extractProfile(hconsensus[column],
245 av_ignoreGapsConsensus);
250 if (aa.autoCalculated && aa.label.startsWith("StrucConsensus"))
252 // TODO implement group structure consensus
254 * if (aa.groupRef != null && aa.groupRef.consensusData != null &&
255 * aa.groupRef.isShowSequenceLogo()) { //TODO check what happens for
256 * group selections return StructureFrequency.extractProfile(
257 * aa.groupRef.consensusData[column], aa.groupRef
258 * .getIgnoreGapsConsensus()); }
260 // TODO extend annotation row to enable dynamic and static profile data
263 if (aa.groupRef == null && aa.sequenceRef == null
264 && av_renderProfile && hStrucConsensus != null
265 && hStrucConsensus.length > column)
267 return StructureFrequency.extractProfile(hStrucConsensus[column],
268 av_ignoreGapsConsensus);
276 * Render the annotation rows associated with an alignment.
280 * data and view settings to render
282 * destination for graphics
284 * row where a mouse event occured (or -1)
286 * first column that will be drawn
288 * last column that will be drawn
289 * @return true if the fadedImage was used for any alignment annotation rows currently being calculated
291 public boolean drawComponent(AwtRenderPanelI annotPanel, AlignViewportI av,
292 Graphics g, int activeRow, int startRes, int endRes)
294 boolean usedFaded=false;
296 // AnnotationPanel needs to implement: ImageObserver, access to
298 updateFromAwtRenderPanel(annotPanel, av);
299 fm = g.getFontMetrics();
300 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
307 boolean validRes = false;
308 boolean validEnd = false;
309 boolean labelAllCols = false;
310 boolean centreColLabels, centreColLabelsDef = av
311 .getCentreColumnLabels();
312 boolean scaleColLabel = false;
313 boolean[] graphGroupDrawn = new boolean[aa.length];
314 int charOffset = 0; // offset for a label
315 float fmWidth, fmScaling = 1f; // scaling for a label to fit it into a
317 Font ofont = g.getFont();
319 for (int i = 0; i < aa.length; i++)
321 AlignmentAnnotation row = aa[i];
322 Annotation[] row_annotations=row.annotations;
327 centreColLabels = row.centreColLabels || centreColLabelsDef;
328 labelAllCols = row.showAllColLabels;
329 scaleColLabel = row.scaleColLabel;
334 if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup])
339 // this is so that we draw the characters below the graph
344 iconOffset = charHeight - fm.getDescent();
348 else if (row.hasText)
350 iconOffset = charHeight - fm.getDescent();
358 if (row.autoCalculated && av.isCalculationInProgress(row))
362 g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0, y
363 - row.height, imgWidth, y, annotationPanel);
364 g.setColor(Color.black);
365 // g.drawString("Calculating "+aa[i].label+"....",20, y-row.height/2);
371 * else if (annotationPanel.av.updatingConservation &&
372 * aa[i].label.equals("Conservation")) {
374 * y += charHeight; g.drawImage(annotationPanel.fadedImage, 0, y -
375 * row.height, annotationPanel.imgWidth, y, 0, y - row.height,
376 * annotationPanel.imgWidth, y, annotationPanel);
378 * g.setColor(Color.black); //
379 * g.drawString("Calculating Conservation.....",20, y-row.height/2);
381 * continue; } else if (annotationPanel.av.updatingConservation &&
382 * aa[i].label.equals("Quality")) {
384 * y += charHeight; g.drawImage(annotationPanel.fadedImage, 0, y -
385 * row.height, annotationPanel.imgWidth, y, 0, y - row.height,
386 * annotationPanel.imgWidth, y, annotationPanel); g.setColor(Color.black);
387 * // / g.drawString("Calculating Quality....",20, y-row.height/2);
391 // first pass sets up state for drawing continuation from left-hand column
393 x = (startRes == 0) ? 0 : -1;
394 while (x < endRes - startRes)
396 if (hasHiddenColumns)
398 column = columnSelection.adjustForHiddenColumns(startRes + x);
399 if (column > row_annotations.length - 1)
406 column = startRes + x;
409 if ((row_annotations == null) || (row_annotations.length <= column)
410 || (row_annotations[column] == null))
422 g.setColor(Color.red);
424 if (columnSelection != null)
426 for (int n = 0; n < columnSelection.size(); n++)
428 int v = columnSelection.columnAt(n);
432 g.fillRect(x * charWidth, y, charWidth, charHeight);
437 if (!row.isValidStruc())
439 g.setColor(Color.orange);
440 g.fillRect((int) row.getInvalidStrucPos() * charWidth, y,
441 charWidth, charHeight);
445 && row_annotations[column].displayCharacter != null
446 && (row_annotations[column].displayCharacter.length() > 0))
449 if (centreColLabels || scaleColLabel)
451 fmWidth = fm.charsWidth(
452 row_annotations[column].displayCharacter
454 row_annotations[column].displayCharacter.length());
458 // justify the label and scale to fit in column
459 if (fmWidth > charWidth)
461 // scale only if the current font isn't already small enough
462 fmScaling = charWidth;
463 fmScaling /= fmWidth;
464 g.setFont(ofont.deriveFont(AffineTransform
465 .getScaleInstance(fmScaling, 1.0)));
466 // and update the label's width to reflect the scaling.
474 .charWidth(row_annotations[column].displayCharacter
477 charOffset = (int) ((charWidth - fmWidth) / 2f);
479 if (row_annotations[column].colour == null)
480 g.setColor(Color.black);
482 g.setColor(row_annotations[column].colour);
484 if (column == 0 || row.graph > 0)
486 g.drawString(row_annotations[column].displayCharacter,
487 (x * charWidth) + charOffset, y + iconOffset);
489 else if (row_annotations[column - 1] == null
491 || !row_annotations[column].displayCharacter
492 .equals(row_annotations[column - 1].displayCharacter) || (row_annotations[column].displayCharacter
493 .length() < 2 && row_annotations[column].secondaryStructure == ' ')))
495 g.drawString(row_annotations[column].displayCharacter, x
496 * charWidth + charOffset, y + iconOffset);
503 char ss = validRes ? row_annotations[column].secondaryStructure
508 // distinguish between forward/backward base-pairing
509 if (row_annotations[column].displayCharacter.indexOf(')') > -1)
517 if ((row_annotations[column].displayCharacter.indexOf(']') > -1) || (row_annotations[column].displayCharacter.indexOf('}') > -1))
523 if (!validRes || (ss != lastSS))
530 drawHelixAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
531 column, validRes, validEnd);
535 drawSheetAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
536 column, validRes, validEnd);
539 case 'S': // Stem case for RNA secondary structure
540 case 's': // and opposite direction
541 drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
542 column, validRes, validEnd);
546 drawNotCanonicalAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
547 column, validRes, validEnd);
550 g.setColor(Color.gray);
551 g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth)
567 lastSSX = (x * charWidth);
574 if (column >= row_annotations.length)
576 column = row_annotations.length - 1;
583 if ((row_annotations == null) || (row_annotations.length <= column)
584 || (row_annotations[column] == null))
600 drawHelixAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
601 column, validRes, validEnd);
605 drawSheetAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
606 column, validRes, validEnd);
609 case 'S': // Stem case for RNA secondary structure
610 drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
611 column, validRes, validEnd);
615 drawNotCanonicalAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
616 column, validRes, validEnd);
619 drawGlyphLine(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
620 column, validRes, validEnd);
625 if (row.graph > 0 && row.graphHeight > 0)
627 if (row.graph == AlignmentAnnotation.LINE_GRAPH)
629 if (row.graphGroup > -1 && !graphGroupDrawn[row.graphGroup])
631 float groupmax = -999999, groupmin = 9999999;
632 for (int gg = 0; gg < aa.length; gg++)
634 if (aa[gg].graphGroup != row.graphGroup)
641 aa[gg].visible = false;
644 if (aa[gg].graphMax > groupmax)
646 groupmax = aa[gg].graphMax;
648 if (aa[gg].graphMin < groupmin)
650 groupmin = aa[gg].graphMin;
654 for (int gg = 0; gg < aa.length; gg++)
656 if (aa[gg].graphGroup == row.graphGroup)
658 drawLineGraph(g, aa[gg], aa[gg].annotations, startRes, endRes, y, groupmin,
659 groupmax, row.graphHeight);
663 graphGroupDrawn[row.graphGroup] = true;
667 drawLineGraph(g, row, row_annotations, startRes, endRes, y, row.graphMin,
668 row.graphMax, row.graphHeight);
671 else if (row.graph == AlignmentAnnotation.BAR_GRAPH)
673 drawBarGraph(g, row, row_annotations, startRes, endRes, row.graphMin,
678 if (row.graph > 0 && row.hasText)
691 private final Color GLYPHLINE_COLOR = Color.gray;
693 private final Color SHEET_COLOUR = Color.green;
695 private final Color HELIX_COLOUR = Color.red;
697 private final Color STEM_COLOUR = Color.blue;
699 private final Color NOTCANONICAL_COLOUR = Color.red;
701 public void drawGlyphLine(Graphics g, Annotation[] row,
702 int lastSSX, int x, int y, int iconOffset, int startRes,
703 int column, boolean validRes, boolean validEnd)
705 g.setColor(GLYPHLINE_COLOR);
706 g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth) - lastSSX, 2);
709 public void drawSheetAnnot(Graphics g, Annotation[] row,
711 int lastSSX, int x, int y, int iconOffset, int startRes,
712 int column, boolean validRes, boolean validEnd)
714 g.setColor(SHEET_COLOUR);
716 if (!validEnd || !validRes || row==null || row[column] == null
717 || row[column].secondaryStructure != 'E')
719 g.fillRect(lastSSX, y + 4 + iconOffset,
720 (x * charWidth) - lastSSX - 4, 7);
721 g.fillPolygon(new int[]
722 { (x * charWidth) - 4, (x * charWidth) - 4, (x * charWidth) },
724 { y + iconOffset, y + 14 + iconOffset, y + 7 + iconOffset },
729 g.fillRect(lastSSX, y + 4 + iconOffset,
730 (x + 1) * charWidth - lastSSX, 7);
735 public void drawHelixAnnot(Graphics g, Annotation[] row,
736 int lastSSX, int x, int y, int iconOffset, int startRes,
737 int column, boolean validRes, boolean validEnd)
739 g.setColor(HELIX_COLOUR);
741 int sCol = (lastSSX / charWidth) + startRes;
743 int x2 = (x * charWidth);
747 int ofs = charWidth / 2;
748 // Off by 1 offset when drawing rects and ovals
749 // to offscreen image on the MAC
750 g.fillRoundRect(lastSSX, y + 4 + iconOffset, x2 - x1, 8, 8, 8);
751 if (sCol == 0 || row[sCol - 1] == null
752 || row[sCol - 1].secondaryStructure != 'H')
757 // g.setColor(Color.orange);
758 g.fillRoundRect(lastSSX, y + 4 + iconOffset, x2 - x1 - ofs + 1, 8,
761 if (!validRes || row[column] == null
762 || row[column].secondaryStructure != 'H')
768 // g.setColor(Color.magenta);
769 g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset, x2 - x1 - ofs
777 if (sCol == 0 || row[sCol - 1] == null
778 || row[sCol - 1].secondaryStructure != 'H')
780 g.fillArc(lastSSX, y + 4 + iconOffset, charWidth, 8, 90, 180);
784 if (!validRes || row[column] == null
785 || row[column].secondaryStructure != 'H')
787 g.fillArc((x * charWidth) - charWidth, y + 4 + iconOffset, charWidth,
792 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
795 public void drawLineGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
796 int eRes, int y, float min, float max, int graphHeight)
798 if (sRes > aa_annotations.length)
805 // Adjustment for fastpaint to left
811 eRes = Math.min(eRes, aa_annotations.length);
819 float range = max - min;
824 y2 = y - (int) ((0 - min / range) * graphHeight);
827 g.setColor(Color.gray);
828 g.drawLine(x - charWidth, y2, (eRes - sRes + 1) * charWidth, y2);
830 eRes = Math.min(eRes, aa_annotations.length);
833 int aaMax = aa_annotations.length - 1;
835 while (x < eRes - sRes)
838 if (hasHiddenColumns)
840 column = columnSelection.adjustForHiddenColumns(column);
848 if (aa_annotations[column] == null
849 || aa_annotations[column - 1] == null)
855 if (aa_annotations[column].colour == null)
856 g.setColor(Color.black);
858 g.setColor(aa_annotations[column].colour);
861 - (int) (((aa_annotations[column - 1].value - min) / range) * graphHeight);
863 - (int) (((aa_annotations[column].value - min) / range) * graphHeight);
865 g.drawLine(x * charWidth - charWidth / 2, y1, x * charWidth
866 + charWidth / 2, y2);
870 if (_aa.threshold != null)
872 g.setColor(_aa.threshold.colour);
873 Graphics2D g2 = (Graphics2D) g;
874 g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
875 BasicStroke.JOIN_ROUND, 3f, new float[]
878 y2 = (int) (y - ((_aa.threshold.value - min) / range) * graphHeight);
879 g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
880 g2.setStroke(new BasicStroke());
884 public void drawBarGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
885 int eRes, float min, float max, int y)
887 if (sRes > aa_annotations.length)
891 Font ofont = g.getFont();
892 eRes = Math.min(eRes, aa_annotations.length);
894 int x = 0, y1 = y, y2 = y;
896 float range = max - min;
900 y2 = y - (int) ((0 - min / (range)) * _aa.graphHeight);
903 g.setColor(Color.gray);
905 g.drawLine(x, y2, (eRes - sRes) * charWidth, y2);
908 int aaMax = aa_annotations.length - 1;
909 boolean renderHistogram = true, renderProfile = true, normaliseProfile = false;
910 // if (aa.autoCalculated && aa.label.startsWith("Consensus"))
912 // TODO: generalise this to have render styles for consensus/profile data
913 if (_aa.groupRef != null)
915 renderHistogram = _aa.groupRef.isShowConsensusHistogram();
916 renderProfile = _aa.groupRef.isShowSequenceLogo();
917 normaliseProfile = _aa.groupRef.isNormaliseSequenceLogo();
921 renderHistogram = av_renderHistogram;
922 renderProfile = av_renderProfile;
923 normaliseProfile = av_normaliseProfile;
926 while (x < eRes - sRes)
929 if (hasHiddenColumns)
931 column = columnSelection.adjustForHiddenColumns(column);
939 if (aa_annotations[column] == null)
944 if (aa_annotations[column].colour == null)
945 g.setColor(Color.black);
947 g.setColor(aa_annotations[column].colour);
950 - (int) (((aa_annotations[column].value - min) / (range)) * _aa.graphHeight);
956 g.fillRect(x * charWidth, y2, charWidth, y1 - y2);
960 g.fillRect(x * charWidth, y1, charWidth, y2 - y1);
963 // draw profile if available
967 int profl[] = getProfileFor(_aa, column);
968 // just try to draw the logo if profl is not null
969 if (profl != null && profl[1] != 0)
971 float ht = normaliseProfile ? y - _aa.graphHeight : y1;
972 double htn = normaliseProfile ? _aa.graphHeight : (y2 - y1);// aa.graphHeight;
979 * profl.length == 74 indicates that the profile of a secondary
980 * structure conservation row was accesed. Therefore dc gets length 2,
981 * to have space for a basepair instead of just a single nucleotide
983 if (profl.length == 74)
991 LineMetrics lm = g.getFontMetrics(ofont).getLineMetrics("Q", g);
992 double scale = 1f / (normaliseProfile ? profl[1] : 100f);
993 float ofontHeight = 1f / lm.getAscent();// magnify to fill box
995 for (int c = 2; c < profl[0];)
997 dc[0] = (char) profl[c++];
999 if (_aa.label.startsWith("StrucConsensus"))
1001 dc[1] = (char) profl[c++];
1005 wdth /= fm.charsWidth(dc, 0, dc.length);
1009 scl = htn * scale * profl[c++];
1010 lm = ofont.getLineMetrics(dc, 0, 1, g.getFontMetrics()
1011 .getFontRenderContext());
1012 g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(
1013 wdth, scl / lm.getAscent())));
1014 lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g);
1016 // Debug - render boxes around characters
1017 // g.setColor(Color.red);
1018 // g.drawRect(x*av.charWidth, (int)ht, av.charWidth,
1020 // g.setColor(profcolour.findColour(dc[0]).darker());
1021 g.setColor(profcolour.findColour(dc[0], column,null));
1023 hght = (ht + (scl - lm.getDescent() - lm.getBaselineOffsets()[lm
1024 .getBaselineIndex()]));
1026 g.drawChars(dc, 0, dc.length, x * charWidth, (int) hght);
1034 if (_aa.threshold != null)
1036 g.setColor(_aa.threshold.colour);
1037 Graphics2D g2 = (Graphics2D) g;
1038 g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
1039 BasicStroke.JOIN_ROUND, 3f, new float[]
1042 y2 = (int) (y - ((_aa.threshold.value - min) / range) * _aa.graphHeight);
1043 g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
1044 g2.setStroke(new BasicStroke());
1048 // used by overview window
1049 public void drawGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int width,
1050 int y, int sRes, int eRes)
1052 eRes = Math.min(eRes, aa_annotations.length);
1053 g.setColor(Color.white);
1054 g.fillRect(0, 0, width, y);
1055 g.setColor(new Color(0, 0, 180));
1059 for (int j = sRes; j < eRes; j++)
1061 if (aa_annotations[j] != null)
1063 if (aa_annotations[j].colour == null)
1064 g.setColor(Color.black);
1066 g.setColor(aa_annotations[j].colour);
1068 height = (int) ((aa_annotations[j].value / _aa.graphMax) * y);
1074 g.fillRect(x, y - height, charWidth, height);