X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Frenderer%2FAnnotationRenderer.java;h=deb2b6f3c383d15004c94cd3818942a21b03e0ff;hb=968f580cc3b1d0ccd16cc00bacce27829b3d694b;hp=8480a342845e0cdcbe56607fd1459816da5b8682;hpb=4dcc7fd17c9fb90ba1830f3d01d30cd232595652;p=jalview.git diff --git a/src/jalview/renderer/AnnotationRenderer.java b/src/jalview/renderer/AnnotationRenderer.java index 8480a34..deb2b6f 100644 --- a/src/jalview/renderer/AnnotationRenderer.java +++ b/src/jalview/renderer/AnnotationRenderer.java @@ -25,7 +25,6 @@ import jalview.analysis.CodingUtils; import jalview.analysis.Rna; import jalview.analysis.StructureFrequency; import jalview.api.AlignViewportI; -import jalview.bin.Jalview; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.datamodel.ColumnSelection; @@ -68,7 +67,7 @@ public class AnnotationRenderer private FontMetrics fm; - private final boolean MAC = Platform.isAMac(); + private final boolean USE_FILL_ROUND_RECT = Platform.isAMacAndNotJS(); boolean av_renderHistogram = true, av_renderProfile = true, av_normaliseProfile = false; @@ -81,9 +80,9 @@ public class AnnotationRenderer private ProfilesI hconsensus; - private Hashtable[] complementConsensus; + private Hashtable[] complementConsensus; - private Hashtable[] hStrucConsensus; + private Hashtable[] hStrucConsensus; private boolean av_ignoreGapsConsensus; @@ -150,6 +149,7 @@ public class AnnotationRenderer */ public void dispose() { + hiddenColumns = null; hconsensus = null; complementConsensus = null; hStrucConsensus = null; @@ -417,8 +417,6 @@ public class AnnotationRenderer return null; } - boolean rna = false; - /** * Render the annotation rows associated with an alignment. * @@ -449,7 +447,7 @@ public class AnnotationRenderer updateFromAwtRenderPanel(annotPanel, av); fm = g.getFontMetrics(); AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation(); - int temp = 0; + // int temp = 0; if (aa == null) { return false; @@ -462,8 +460,8 @@ public class AnnotationRenderer boolean validRes = false; boolean validEnd = false; boolean labelAllCols = false; - boolean centreColLabels; - boolean centreColLabelsDef = av.isCentreColumnLabels(); +// boolean centreColLabels; +// boolean centreColLabelsDef = av.isCentreColumnLabels(); boolean scaleColLabel = false; final AlignmentAnnotation consensusAnnot = av .getAlignmentConsensusAnnotation(); @@ -471,14 +469,9 @@ public class AnnotationRenderer .getAlignmentStrucConsensusAnnotation(); final AlignmentAnnotation complementConsensusAnnot = av .getComplementConsensusAnnotation(); - boolean renderHistogram = true, renderProfile = true, - normaliseProfile = false, isRNA = rna; BitSet graphGroupDrawn = new BitSet(); int charOffset = 0; // offset for a label - float fmWidth, fmScaling = 1f; // scaling for a label to fit it into a - // column. - Font ofont = g.getFont(); // \u03B2 \u03B1 // debug ints int yfrom = 0, f_i = 0, yto = 0, f_to = 0; @@ -486,38 +479,35 @@ public class AnnotationRenderer for (int i = 0; i < aa.length; i++) { AlignmentAnnotation row = aa[i]; - isRNA = row.isRNA(); + boolean renderHistogram = true; + boolean renderProfile = false; + boolean normaliseProfile = false; + boolean isRNA = row.isRNA(); + + // check if this is a consensus annotation row and set the display + // settings appropriately + // TODO: generalise this to have render styles for consensus/profile + // data + if (row.groupRef != null && row == row.groupRef.getConsensus()) { - // check if this is a consensus annotation row and set the display - // settings appropriately - // TODO: generalise this to have render styles for consensus/profile - // data - if (row.groupRef != null && row == row.groupRef.getConsensus()) - { - renderHistogram = row.groupRef.isShowConsensusHistogram(); - renderProfile = row.groupRef.isShowSequenceLogo(); - normaliseProfile = row.groupRef.isNormaliseSequenceLogo(); - } - else if (row == consensusAnnot || row == structConsensusAnnot - || row == complementConsensusAnnot) - { - renderHistogram = av_renderHistogram; - renderProfile = av_renderProfile; - normaliseProfile = av_normaliseProfile; - } - else - { - renderHistogram = true; - // don't need to set render/normaliseProfile since they are not - // currently used in any other annotation track renderer - } + renderHistogram = row.groupRef.isShowConsensusHistogram(); + renderProfile = row.groupRef.isShowSequenceLogo(); + normaliseProfile = row.groupRef.isNormaliseSequenceLogo(); } + else if (row == consensusAnnot || row == structConsensusAnnot + || row == complementConsensusAnnot) + { + renderHistogram = av_renderHistogram; + renderProfile = av_renderProfile; + normaliseProfile = av_normaliseProfile; + } + Annotation[] row_annotations = row.annotations; if (!row.visible) { continue; } - centreColLabels = row.centreColLabels || centreColLabelsDef; +// centreColLabels = row.centreColLabels || centreColLabelsDef; labelAllCols = row.showAllColLabels; scaleColLabel = row.scaleColLabel; lastSS = ' '; @@ -654,43 +644,24 @@ public class AnnotationRenderer && (displayChar.length() > 0)) { Graphics2D gg = ((Graphics2D) g); - AffineTransform t = gg.getTransform(); - fmWidth = fm.charsWidth(displayChar.toCharArray(), 0, + float fmWidth = fm.charsWidth(displayChar.toCharArray(), 0, displayChar.length()); - if (/* centreColLabels || */scaleColLabel) + + /* + * shrink label width to fit in column, if that is + * both configured and necessary + */ + boolean scaledToFit = false; + float fmScaling = 1f; + if (scaleColLabel && fmWidth > charWidth) { - // fmWidth = fm.charsWidth(displayChar.toCharArray(), 0, - // displayChar.length()); - // - // if (scaleColLabel) - // { - // justify the label and scale to fit in column - if (fmWidth > charWidth) - { - // scale only if the current font isn't already small enough - fmScaling = charWidth; - fmScaling /= fmWidth; - if (Jalview.isJS()) - { - gg.setFont(ofont); - gg.transform(AffineTransform.getScaleInstance(fmScaling, - 1.0)); - } - else - { - g.setFont(ofont.deriveFont(AffineTransform - .getScaleInstance(fmScaling, 1.0))); - } - // and update the label's width to reflect the scaling. - fmWidth = charWidth; - } - // } + scaledToFit = true; + fmScaling = charWidth; + fmScaling /= fmWidth; + // and update the label's width to reflect the scaling. + fmWidth = charWidth; } - // TODO is it ok to use width of / show all characters here? - // else - // { - // fmWidth = fm.charWidth(displayChar.charAt(0)); - // } + charOffset = (int) ((charWidth - fmWidth) / 2f); if (row_annotations[column].colour == null) @@ -702,10 +673,29 @@ public class AnnotationRenderer gg.setColor(row_annotations[column].colour); } + /* + * draw the label, unless it is the same secondary structure + * symbol (excluding RNA Helix) as the previous column + */ + final int xPos = (x * charWidth) + charOffset; + final int yPos = y + iconOffset; + + /* + * translate to drawing position _before_ applying any scaling + */ + gg.translate(xPos, yPos); + if (scaledToFit) + { + /* + * use a scaling transform to make the label narrower + * (JalviewJS doesn't have Font.deriveFont(AffineTransform)) + */ + gg.transform( + AffineTransform.getScaleInstance(fmScaling, 1.0)); + } if (column == 0 || row.graph > 0) { - gg.drawString(displayChar, (x * charWidth) + charOffset, - y + iconOffset); + gg.drawString(displayChar, 0, 0); } else if (row_annotations[column - 1] == null || (labelAllCols || !displayChar.equals( @@ -713,11 +703,18 @@ public class AnnotationRenderer || (displayChar.length() < 2 && row_annotations[column].secondaryStructure == ' '))) { - gg.drawString(displayChar, x * charWidth + charOffset, - y + iconOffset); + gg.drawString(displayChar, 0, 0); } - g.setFont(ofont); - gg.setTransform(t); + if (scaledToFit) + { + /* + * undo scaling before translating back + * (restoring saved transform does NOT work in JS PDFGraphics!) + */ + gg.transform(AffineTransform + .getScaleInstance(1D / fmScaling, 1.0)); + } + gg.translate(-xPos, -yPos); } } if (row.hasIcons) @@ -778,7 +775,7 @@ public class AnnotationRenderer if (x > -1) { - int nb_annot = x - temp; + // int nb_annot = x - temp; // System.out.println("\t type :"+lastSS+"\t x :"+x+"\t nbre // annot :"+nb_annot); switch (lastSS) @@ -787,7 +784,7 @@ public class AnnotationRenderer case ')': // and opposite direction drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); - temp = x; + // temp = x; break; case 'H': @@ -870,13 +867,13 @@ public class AnnotationRenderer drawNotCanonicalAnnot(g, nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); - temp = x; + // temp = x; break; default: g.setColor(Color.gray); g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth) - lastSSX, 2); - temp = x; + // temp = x; break; } } @@ -1117,7 +1114,7 @@ public class AnnotationRenderer public static final Color STEM_COLOUR = Color.blue; - private Color sdNOTCANONICAL_COLOUR; + // private Color sdNOTCANONICAL_COLOUR; void drawGlyphLine(Graphics g, Annotation[] row, int lastSSX, int x, int y, int iconOffset, int startRes, int column, boolean validRes, @@ -1165,7 +1162,7 @@ public class AnnotationRenderer int x1 = lastSSX; int x2 = (x * charWidth); - if (MAC) + if (USE_FILL_ROUND_RECT) { int ofs = charWidth / 2; // Off by 1 offset when drawing rects and ovals @@ -1393,7 +1390,8 @@ public class AnnotationRenderer boolean isStructureProfile = profl[0] == AlignmentAnnotation.STRUCTURE_PROFILE; boolean isCdnaProfile = profl[0] == AlignmentAnnotation.CDNA_PROFILE; float ht = normaliseProfile ? y - _aa.graphHeight : y1; - double htn = normaliseProfile ? _aa.graphHeight : (y2 - y1);// aa.graphHeight; + final double normaliseFactor = normaliseProfile ? _aa.graphHeight + : (y2 - y1); /** * Render a single base for a sequence profile, a base pair for @@ -1444,8 +1442,14 @@ public class AnnotationRenderer s = new String(dc); } // next profl[] position is profile % for the character(s) - - double newHeight = htn * scale * profl[c++]; + + int percent = profl[c++]; + if (percent == 0) + { + // failsafe in case a count rounds down to 0% + continue; + } + double newHeight = normaliseFactor * scale * percent; /* * Set character colour as per alignment colour scheme; use the @@ -1471,39 +1475,52 @@ public class AnnotationRenderer // (int)(scl)); // g.setColor(profcolour.findColour(dc[0]).darker()); - double sx = 1f * charWidth / fm.charsWidth(dc, 0, dc.length); + double sx = 1f * charWidth / fm.charsWidth(dc, 0, dc.length); double sy = newHeight / asc; - double newAsc = asc * sy; + double newAsc = asc * sy; double newDec = dec * sy; - // it is not necessary to recalculated lm for the new font. + // it is not necessary to recalculate lm for the new font. // note: lm.getBaselineOffsets()[lm.getBaselineIndex()]) must be 0 // by definition. Was: - // int hght = (int) (ht + (newAsc - newDec - lm.getBaselineOffsets()[lm.getBaselineIndex()])); - - // original: - - if (/** @j2sNative false && */ true) { - int hght = (int) (ht + (newAsc - newDec)); // Q: why " - newDec " ? (0,0) is on the font baseline, I think - Font font = ofont.deriveFont(AffineTransform.getScaleInstance(sx, sy)); - g.setFont(font); - g.drawChars(dc, 0, dc.length, x * charWidth, hght); - ht += newHeight; - } else { - // SwingJS does not implement font.deriveFont() - // this is off by a very small amount. - int hght2 = (int) (ht2 + newAsc); - Graphics2D gg = (Graphics2D) g.create(); - gg.setFont(ofont); + // int hght = (int) (ht + (newAsc - newDec); + // - lm.getBaselineOffsets()[lm.getBaselineIndex()])); + + if (Platform.isJS()) + { + /* + * SwingJS does not implement font.deriveFont() + * so use a scaling transform to draw instead, + * this is off by a very small amount + */ + final int hght = (int) (ht2 + (newAsc - newDec)); + Graphics2D gg = (Graphics2D) g; + int xShift = (int) Math.round(x * charWidth / sx); + int yShift = (int) Math.round(hght / sy); gg.transform(AffineTransform.getScaleInstance(sx, sy)); - //System.out.println("sx " + sx + " sy " + sy + " " + hght + " " + lm.getDescent() + " " + dec + " " + newDec + " " + lm.getAscent() + " " + asc + " " + newAsc); - gg.drawString(s, (int) (x * charWidth / sx), - (int) (hght2 / sy)); - gg.dispose(); + gg.drawString(s, xShift, yShift); + gg.transform( + AffineTransform.getScaleInstance(1D / sx, 1D / sy)); ht2 += newHeight; } - + else + /** + * Java only + * + * @j2sIgnore + */ + { + // Java ('normal') method is to scale the font to fit + + final int hght = (int) (ht + (newAsc - newDec)); + Font font = ofont + .deriveFont(AffineTransform.getScaleInstance(sx, sy)); + g.setFont(font); + g.drawChars(dc, 0, dc.length, x * charWidth, hght); + g.setFont(ofont); + + ht += newHeight; + } } - g.setFont(ofont); } } x++; @@ -1514,7 +1531,7 @@ public class AnnotationRenderer Graphics2D g2 = (Graphics2D) g; g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 3f, new float[] - { 5f, 3f }, 0f)); + { 5f, 3f }, 0f)); y2 = (int) (y - ((_aa.threshold.value - min) / range) * _aa.graphHeight);