+ /**
+ * Property to set text antialiasing method
+ */
+ private static final String TEXT_ANTIALIAS_METHOD = "TEXT_ANTIALIAS_METHOD";
+
+ private static final Object textAntialiasMethod;
+
+ static
+ {
+ final String textAntialiasMethodPref = Cache
+ .getDefault(TEXT_ANTIALIAS_METHOD, "GASP");
+ switch (textAntialiasMethodPref)
+ {
+ case "ON":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_ON;
+ break;
+ case "GASP":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_GASP;
+ break;
+ case "LCD_HBGR":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
+ break;
+ case "LCD_HRGB":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
+ break;
+ case "LCD_VBGR":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR;
+ break;
+ case "LCD_VRGB":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB;
+ break;
+ case "OFF":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
+ break;
+ case "DEFAULT":
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
+ break;
+ default:
+ jalview.bin.Console.warn(TEXT_ANTIALIAS_METHOD + " value '"
+ + textAntialiasMethodPref
+ + "' not recognised, defaulting to 'GASP'. See https://docs.oracle.com/javase/8/docs/api/java/awt/RenderingHints.html#KEY_TEXT_ANTIALIASING");
+ textAntialiasMethod = RenderingHints.VALUE_TEXT_ANTIALIAS_GASP;
+ }
+ }
+
+ public AnnotationRenderer()
+ {
+ this(false);
+ }
+
+ /**
+ * Create a new annotation Renderer
+ *
+ * @param debugRedraw
+ * flag indicating if timing and redraw parameter info should be
+ * output
+ */
+ public AnnotationRenderer(boolean debugRedraw)
+ {
+ this.debugRedraw = debugRedraw;
+ }
+
+ /**
+ * Remove any references and resources when this object is no longer required
+ */
+ public void dispose()
+ {
+ hiddenColumns = null;
+ hconsensus = null;
+ complementConsensus = null;
+ hStrucConsensus = null;
+ fadedImage = null;
+ annotationPanel = null;
+ rendererFactoryI = null;
+ }
+
+ void drawStemAnnot(Graphics g, Annotation[] row_annotations, int lastSSX,
+ int x, int y, int iconOffset, int startRes, int column,
+ boolean validRes, boolean validEnd)
+ {
+ int sCol = (lastSSX / charWidth)
+ + hiddenColumns.visibleToAbsoluteColumn(startRes);
+ int x1 = lastSSX;
+ int x2 = (x * charWidth);
+
+ char dc = (column == 0 || row_annotations[column - 1] == null) ? ' '
+ : row_annotations[column - 1].secondaryStructure;
+
+ boolean diffupstream = sCol == 0 || row_annotations[sCol - 1] == null
+ || dc != row_annotations[sCol - 1].secondaryStructure
+ || !validEnd;
+ boolean diffdownstream = !validRes || !validEnd
+ || row_annotations[column] == null
+ || dc != row_annotations[column].secondaryStructure;
+
+ if (diffupstream || diffdownstream)
+ {
+ // draw glyphline under arrow
+ drawGlyphLine(g, lastSSX, x, y, iconOffset);
+ }
+ g.setColor(STEM_COLOUR);
+
+ if (column > 0 && Rna.isClosingParenthesis(dc))
+ {
+ if (diffupstream)
+ // if (validRes && column>1 && row_annotations[column-2]!=null &&
+ // dc.equals(row_annotations[column-2].displayCharacter))
+ {
+ /*
+ * if new annotation with a closing base pair half of the stem,
+ * display a backward arrow
+ */
+ fillPolygon(g, new int[] { lastSSX + 5, lastSSX + 5, lastSSX },
+ new int[]
+ { y + iconOffset + 1, y + 13 + iconOffset,
+ y + 7 + iconOffset },
+ 3);
+ x1 += 5;
+ }
+ if (diffdownstream)
+ {
+ x2 -= 1;
+ }
+ }
+ else
+ {
+ // display a forward arrow
+ if (diffdownstream)
+ {
+ /*
+ * if annotation ending with an opeing base pair half of the stem,
+ * display a forward arrow
+ */
+ fillPolygon(g, new int[] { x2 - 6, x2 - 6, x2 - 1 },
+ new int[]
+ { y + iconOffset + 1, y + 13 + iconOffset,
+ y + 7 + iconOffset },
+ 3);
+ x2 -= 5;
+ }
+ if (diffupstream)
+ {
+ x1 += 1;
+ }
+ }
+ // draw arrow body
+ unsetAntialias(g);
+ fillRect(g, x1, y + 4 + iconOffset, x2 - x1, 6);
+ }
+
+ void drawNotCanonicalAnnot(Graphics g, Color nonCanColor,