Package org.openscience.jchempaint.renderer.visitor

Source Code of org.openscience.jchempaint.renderer.visitor.AWTDrawVisitor

/* $Revision$ $Author$ $Date$
*
*  Copyright (C) 2008 Gilleain Torrance <gilleain.torrance@gmail.com>
*
*  Contact: cdk-devel@list.sourceforge.net
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2.1
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package org.openscience.jchempaint.renderer.visitor;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.vecmath.Point2d;
import javax.vecmath.Vector2d;

import org.openscience.cdk.geometry.BondTools;
import org.openscience.cdk.renderer.elements.Bounds;
import org.openscience.cdk.renderer.font.AWTFontManager;
import org.openscience.cdk.renderer.font.IFontManager;
import org.openscience.jchempaint.renderer.JChemPaintRendererModel;
import org.openscience.cdk.renderer.elements.ArrowElement;
import org.openscience.cdk.renderer.elements.AtomSymbolElement;
import org.openscience.cdk.renderer.elements.ElementGroup;
import org.openscience.cdk.renderer.elements.GeneralPath;
import org.openscience.cdk.renderer.elements.IRenderingElement;
import org.openscience.cdk.renderer.elements.LineElement;
import org.openscience.cdk.renderer.elements.OvalElement;
import org.openscience.cdk.renderer.elements.PathElement;
import org.openscience.cdk.renderer.elements.RectangleElement;
import org.openscience.jchempaint.renderer.elements.TextElement;
import org.openscience.jchempaint.renderer.elements.TextGroupElement;
import org.openscience.cdk.renderer.elements.WedgeLineElement;
import org.openscience.jchempaint.renderer.elements.WigglyLineElement;
import org.openscience.cdk.renderer.elements.path.Type;


/**
* @cdk.module renderawt
*/
public class AWTDrawVisitor extends AbstractAWTDrawVisitor {

    /**
     * The font manager cannot be set by the constructor as it needs to
     * be managed by the Renderer.
     */
    private AWTFontManager fontManager;

    /**
     * The renderer model cannot be set by the constructor as it needs to
     * be managed by the Renderer.
     */
    private JChemPaintRendererModel rendererModel;

    private final Map<Integer, BasicStroke> strokeMap =
            new HashMap<Integer, BasicStroke>();

    private final Map<TextAttribute, Object> map =
            new Hashtable<TextAttribute, Object>();

    private final Graphics2D g;

    public AWTDrawVisitor(Graphics2D g) {
        this.g = g;
        this.fontManager = null;
        this.rendererModel = null;
        this.fm = g.getFontMetrics();

        map.put(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB);
    }

    public void visitElementGroup(ElementGroup elementGroup) {
        elementGroup.visitChildren(this);
    }

    public void visit(ElementGroup elementGroup) {
        elementGroup.visitChildren(this);
    }

    public void visit(ArrowElement line) {
        Stroke savedStroke = this.g.getStroke();

        int w = (int) (line.width * this.transform.getScaleX());
        if (strokeMap.containsKey(w)) {
            this.g.setStroke(strokeMap.get(w));
        }
        else {
            BasicStroke stroke = new BasicStroke(w);
            this.g.setStroke(stroke);
            strokeMap.put(w, stroke);
        }
        this.g.setColor(line.color);
        int[] a = this.transformPoint(line.startX, line.startY);
        int[] b = this.transformPoint(line.endX, line.endY);
        this.g.drawLine(a[0], a[1], b[0], b[1]);
        double arrowWidth = rendererModel.getArrowHeadWidth() / rendererModel.getScale();
        double lenghtOfArrow = Math.sqrt(Math.pow(Math.abs(line.startX - line.endX), 2) + Math.pow(Math.abs(line.startY - line.endY), 2));
        double fractionOfHead = arrowWidth / lenghtOfArrow;
        //headpoint is a line on the arrow arrowWidth away from end
        Point2d headPoint = new Point2d();
        if (line.startX < line.endX)
            headPoint.x = line.startX + (line.endX - line.startX) * (fractionOfHead);
        else
            headPoint.x = line.endX + (line.startX - line.endX) * (1 - fractionOfHead);
        if (line.startY < line.endY)
            headPoint.y = line.startY + (line.endY - line.startY) * (fractionOfHead);
        else
            headPoint.y = line.endY + (line.startY - line.endY) * (1 - fractionOfHead);
        //rotate headpoint in both directions to get end points of arrow
        double relativex = headPoint.x - line.startX;
        double relativey = headPoint.y - line.startY;
        double angle = Math.PI / 6;
        double costheta = Math.cos(angle);
        double sintheta = Math.sin(angle);
        Point2d firstArrowPoint = new Point2d();
        firstArrowPoint.x = relativex * costheta - relativey * sintheta + line.startX;
        firstArrowPoint.y = relativex * sintheta + relativey * costheta + line.startY;
        int[] firstArrowPointCoords = this.transformPoint(firstArrowPoint.x, firstArrowPoint.y);
        this.g.drawLine(a[0], a[1], firstArrowPointCoords[0], firstArrowPointCoords[1]);
        angle = -Math.PI / 6;
        costheta = Math.cos(angle);
        sintheta = Math.sin(angle);
        Point2d secondArrowPoint = new Point2d();
        secondArrowPoint.x = relativex * costheta - relativey * sintheta + line.startX;
        secondArrowPoint.y = relativex * sintheta + relativey * costheta + line.startY;
        int[] secondArrowPointCoords = this.transformPoint(secondArrowPoint.x, secondArrowPoint.y);
        this.g.drawLine(a[0], a[1], secondArrowPointCoords[0], secondArrowPointCoords[1]);
        this.g.setStroke(savedStroke);
    }
   
   
    public void visit(LineElement line) {
        Stroke savedStroke = this.g.getStroke();
       
        int w = (int) (line.width * this.transform.getScaleX());
        if (w < 1) {
            w=1;
        }

        if (strokeMap.containsKey(w)) {
            this.g.setStroke(strokeMap.get(w));
        } else {
            BasicStroke stroke = new BasicStroke(w, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            this.g.setStroke(stroke);
            strokeMap.put(w, stroke);
        }
       
        this.g.setColor(line.color);
        double[] a = this.transformPointD(line.firstPointX, line.firstPointY);
        double[] b = this.transformPointD(line.secondPointX, line.secondPointY);
        this.g.draw(new Line2D.Double(a[0], a[1], b[0], b[1]));
       
        this.g.setStroke(savedStroke);
    }

    public void visit(OvalElement oval) {
        this.g.setColor(oval.color);
        int[] min =
            this.transformPoint(oval.xCoord - oval.radius, oval.yCoord - oval.radius);
        int[] max =                                             
            this.transformPoint(oval.xCoord + oval.radius, oval.yCoord + oval.radius);
        int w = max[0] - min[0];
        int h = min[1] - max[1];
        if (oval.fill) {
            this.g.fillOval(min[0], max[1], w, h);
        } else {
            this.g.drawOval(min[0], max[1], w, h);
        }
    }

    public void visit(TextElement textElement) {
        this.g.setFont(this.fontManager.getFont());
        Point p = this.getTextBasePoint(
                textElement.text, textElement.x, textElement.y, g);
        Rectangle2D textBounds =
                this.getTextBounds(
                        textElement.text, textElement.x, textElement.y, g,
                        rendererModel.getZoomFactor());
       
        this.g.setColor(textElement.backColor!=null ? textElement.backColor : this.rendererModel.getBackColor());
        this.g.fill(textBounds);
        this.g.setColor(textElement.color);
        if (textElement.extraZoom!=null)
          this.g.setFont(new Font (this.g.getFont().getName(), 1, (int)(this.g.getFont().getSize()*textElement.extraZoom))) ;
        this.g.drawString(textElement.text, p.x, p.y);
       
    }
   
    public void visit(WedgeLineElement wedge) {
        // make the vector normal to the wedge axis
        Vector2d normal =
            new Vector2d(wedge.firstPointY - wedge.secondPointY, wedge.secondPointX - wedge.firstPointX);
        normal.normalize();
        normal.scale(rendererModel.getWedgeWidth() / rendererModel.getScale())
       
        // make the triangle corners
        Point2d vertexA = new Point2d(wedge.firstPointX, wedge.firstPointY);
        Point2d vertexB = new Point2d(wedge.secondPointX, wedge.secondPointY);
        Point2d vertexC = new Point2d(vertexB);
        vertexB.add(normal);
        vertexC.sub(normal);
        this.g.setColor(wedge.color);
        if (wedge.type == WedgeLineElement.TYPE.DASHED) {
            this.drawDashedWedge(vertexA, vertexB, vertexC);
        } else if(wedge.type == WedgeLineElement.TYPE.WEDGED){
            this.drawFilledWedge(vertexA, vertexB, vertexC);
        } else {
          this.drawCrissCrossWedge(vertexA, vertexB, vertexC);
        }
    }
   
    public void visit(WigglyLineElement wedge) {
        // make the endpoints
        Point2d vertexA = new Point2d(wedge.firstPointX, wedge.firstPointY);
        Point2d vertexB = new Point2d(wedge.secondPointX, wedge.secondPointY);
        this.g.setColor(wedge.color);
       
        // store the current stroke
        Stroke storedStroke = this.g.getStroke();
        this.g.setStroke(new BasicStroke(1));
       
        // calculate the distances between circles
        double distance = vertexB.distance(vertexA);
        double gapFactor = 0.1;
        double gap = distance * gapFactor;
        double numberOfCircles = distance*5;
       
        int diameter = (int)(rendererModel.getBondLength()*rendererModel.getZoomFactor()*1.2*gapFactor)+2;
        double d = 0;
        double rad=BondTools.giveAngleBothMethods(new Point2d(wedge.firstPointX,wedge.firstPointY), new Point2d(wedge.firstPointX+100,wedge.firstPointY), new Point2d(wedge.secondPointX,wedge.secondPointY), true);
        int degrees=(int)(360*(rad/(2*Math.PI)));
        // draw by interpolating along the imaginary straight line
        for (int i = 0; i < numberOfCircles; i++) {
            Point2d p1 = new Point2d();
            p1.interpolate(vertexA, vertexB, d);
            Point2d p2 = new Point2d();
            p2.interpolate(vertexA, vertexB, d+1/numberOfCircles);
           
            int[] p1T = this.transformPoint(p1.x, p1.y);
            int[] p2T = this.transformPoint(p2.x, p2.y);
            int wh = (int) (new Point2d(p1T[0],p1T[1]).distance(new Point2d(p2T[0],p2T[1])));

            this.g.drawArc(p1T[0]-diameter, p1T[1]-diameter/2, wh,wh, i % 2 == 0 ? degrees : (degrees+180)%360, 180);

            if (distance * (d + gapFactor) >= distance) {
                break;
            } else {
                d += 1/numberOfCircles;
            }
        }
        this.g.setStroke(storedStroke);
       
    }

    private void drawCrissCrossWedge(Point2d vertexA, Point2d vertexB,
      Point2d vertexC) {
        // store the current stroke
        Stroke storedStroke = this.g.getStroke();
        this.g.setStroke(new BasicStroke(1));
       
        // calculate the distances between lines
        double distance = vertexB.distance(vertexA);
        double gapFactor = 0.1;
        double gap = distance * gapFactor;
        double numberOfDashes = distance / gap;
        double d = gapFactor;
        int[] old=null;
       
        // draw by interpolating along the edges of the triangle
        for (int i = 0; i < numberOfDashes; i++) {
            double d2 = d-gapFactor;
            Point2d p1 = new Point2d();
            p1.interpolate(vertexA, vertexB, d);
            Point2d p2 = new Point2d();
            p2.interpolate(vertexA, vertexC, d2);
            int[] p1T = this.transformPoint(p1.x, p1.y);
            int[] p2T = this.transformPoint(p2.x, p2.y);
            this.g.drawLine(p1T[0], p1T[1], p2T[0], p2T[1]);
            if(old==null)
              old = p2T;
            this.g.drawLine(old[0], old[1], p2T[0], p2T[1]);
            old = p1T;
            if (distance * (d + gapFactor) >= distance) {
                break;
            } else {
                d += gapFactor*2;
            }
        }
        this.g.setStroke(storedStroke);
  }

  private void drawFilledWedge(
            Point2d vertexA, Point2d vertexB, Point2d vertexC) {
        int[] pB = this.transformPoint(vertexB.x, vertexB.y);
        int[] pC = this.transformPoint(vertexC.x, vertexC.y);
        int[] pA = this.transformPoint(vertexA.x, vertexA.y);
       
        int[] xs = new int[] { pB[0], pC[0], pA[0] };
        int[] ys = new int[] { pB[1], pC[1], pA[1] };
        this.g.fillPolygon(xs, ys, 3);
    }
   
    private void drawDashedWedge(
            Point2d vertexA, Point2d vertexB, Point2d vertexC) {
        // store the current stroke
        Stroke storedStroke = this.g.getStroke();
        this.g.setStroke(new BasicStroke(1));
       
        // calculate the distances between lines
        double distance = vertexB.distance(vertexA);
        double gapFactor = 0.1;
        double gap = distance * gapFactor;
        double numberOfDashes = distance / gap;
        double d = 0;
       
        // draw by interpolating along the edges of the triangle
        for (int i = 0; i < numberOfDashes; i++) {
            Point2d p1 = new Point2d();
            p1.interpolate(vertexA, vertexB, d);
            Point2d p2 = new Point2d();
            p2.interpolate(vertexA, vertexC, d);
            int[] p1T = this.transformPoint(p1.x, p1.y);
            int[] p2T = this.transformPoint(p2.x, p2.y);
            this.g.drawLine(p1T[0], p1T[1], p2T[0], p2T[1]);
            if (distance * (d + gapFactor) >= distance) {
                break;
            } else {
                d += gapFactor;
            }
        }
        this.g.setStroke(storedStroke);
    }
   
    public void visit(AtomSymbolElement atomSymbol) {
        this.g.setFont(this.fontManager.getFont());
        Point p =
            super.getTextBasePoint(
                    atomSymbol.text, atomSymbol.xCoord, atomSymbol.yCoord, g);
        Rectangle2D textBounds =
            this.getTextBounds(atomSymbol.text, atomSymbol.xCoord, atomSymbol.yCoord, g,
                    rendererModel.getZoomFactor());
        this.g.setColor(this.rendererModel.getBackColor());
        this.g.fill(textBounds);
        this.g.setColor(atomSymbol.color);
        this.g.drawString(atomSymbol.text, p.x, p.y);
       
        int offset = 10;    // XXX
        String chargeString;
        if (atomSymbol.formalCharge == 0) {
            return;
        } else if (atomSymbol.formalCharge == 1) {
            chargeString = "+";
        } else if (atomSymbol.formalCharge > 1) {
            chargeString = atomSymbol.formalCharge + "+";
        } else if (atomSymbol.formalCharge == -1) {
            chargeString = "-";
        } else if (atomSymbol.formalCharge < -1) {
            int absCharge = Math.abs(atomSymbol.formalCharge);
            chargeString = absCharge + "-";
        } else {
            return;
        }
      
        int x = (int) textBounds.getCenterX();
        int y = (int) textBounds.getCenterY();
        if (atomSymbol.alignment == 1) {           // RIGHT
            this.g.drawString(
                    chargeString, x + offset, (int)textBounds.getMinY());
        } else if (atomSymbol.alignment == -1) {   // LEFT
            this.g.drawString(
                    chargeString, x - offset, (int)textBounds.getMinY());
        } else if (atomSymbol.alignment == 2) {    // TOP
            this.g.drawString(
                    chargeString, x, y - offset);
        } else if (atomSymbol.alignment == -2) {   // BOT
            this.g.drawString(
                    chargeString, x, y + offset);
        }

    }
   
    public void visit(RectangleElement rectangle) {
        int[] p1 = this.transformPoint(rectangle.xCoord, rectangle.yCoord);
        int[] p2 = this.transformPoint(
                rectangle.xCoord + rectangle.width, rectangle.yCoord + rectangle.height);
        this.g.setColor(rectangle.color);
        if (rectangle.filled) {
            this.g.fillRect(p1[0], p1[1], p2[0] - p1[0], p2[1] - p1[1]);
        } else {
            this.g.drawRect(p1[0], p1[1], p2[0] - p1[0], p2[1] - p1[1]);
        }
    }
   
    public void visit(PathElement path) {
        this.g.setColor(path.color);
        for (int i = 1; i < path.points.size(); i++) {
            Point2d point1 = path.points.get(i - 1);
            Point2d point2 = path.points.get(i);
            int[] p1 = this.transformPoint(point1.x, point1.y);
            int[] p2 = this.transformPoint(point2.x, point2.y);
            this.g.drawLine(p1[0], p1[1], p2[0], p2[1]);
        }
    }
   
    public void visit(GeneralPath path) {
        this.g.setColor(path.color);
        Path2D cpy = new Path2D.Double();
        cpy.append(getPathIterator(path, transform), false);

        if (path.fill) {
            this.g.fill(cpy);
        } else {
            Stroke stroke = this.g.getStroke();
            this.g.setStroke(new BasicStroke((float) (path.stroke * transform.getScaleX()), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            this.g.draw(cpy);
            this.g.setStroke(stroke);
        }
    }

    private static PathIterator getPathIterator(final GeneralPath path,
            final AffineTransform transform) {
        return new PathIterator() {

            int index;

            private int type(Type type) {
                switch ( type ) {
                    case MoveTo: return SEG_MOVETO;
                    case LineTo: return SEG_LINETO;
                    case QuadTo: return SEG_QUADTO;
                    case CubicTo: return SEG_CUBICTO;
                    case Close: return SEG_CLOSE;
                    default: return SEG_CLOSE;
                }
            }
            public void next() {
                index++;
            }

            public boolean isDone() {
                return index>= path.elements.size();
            }

            public int getWindingRule() {
                return path.winding;
            }

            public int currentSegment(double[] coords) {
                path.elements.get(index).points(coords);
                transform.transform(coords, 0, coords, 0, 3);
                return type(path.elements.get(index).type);
            }

            public int currentSegment( float[] coords ) {
                double[] doubleCoords = new double[6];
                int type = currentSegment(doubleCoords);
                for (int i = 0; i < 5; i++)
                    coords[i] = (float) doubleCoords[i];
                return type;
            }
        };
    }

    public void visit(TextGroupElement textGroup) {
        this.g.setFont(this.fontManager.getFont());
        Point p =
            super.getTextBasePoint(
                    textGroup.text, textGroup.x, textGroup.y, g);
        Rectangle2D textBounds =
            this.getTextBounds(textGroup.text, textGroup.x, textGroup.y, g,
                    rendererModel.getZoomFactor());
        this.g.setColor(textGroup.backColor!=null ? textGroup.backColor : this.rendererModel.getBackColor());
        this.g.fill(textBounds);
        this.g.setColor(textGroup.color);
        this.g.drawString(textGroup.text, p.x, p.y);
       
        int x = (int) textBounds.getCenterX();
        int y = (int) textBounds.getCenterY();
        int x1 = (int) textBounds.getMinX();
        int y1 = (int) textBounds.getMinY();
        int x2 = p.x + (int)textBounds.getWidth();
        int y2 = (int) textBounds.getMaxY();

        for (TextGroupElement.Child child : textGroup.children) {
            //First we calculate the child bounds just to find width and height
            Rectangle2D childBounds = getTextBounds(child.text, 0, 0, g,
                    rendererModel.getZoomFactor());
            int oW = (int)childBounds.getWidth();
            int oH = (int)childBounds.getHeight();

            //use that to actually calculate the position
            int cx;
            int cy;
           
            switch (child.position) {
                case NE:
                    cx = x2;
                    cy = y1;
                    break;
                case N:
                    cx = x1;
                    cy = y1;
                    break;
                case NW:
                    cx = x1 - oW;
                    cy = y1;
                    break;
                case W:
                    cx = x1 - oW;
                    cy = p.y;
                    break;
                case SW:
                    cx = x1 - oW;
                    cy = y1 + oH;
                    break;
                case S:
                    cx = x1;
                    cy = y2 + oH;
                    break;
                case SE:
                    cx = x2;
                    cy = y2 + oH;
                    break;
                case E:
                    cx = x2;
                    cy = p.y;
                    break;
                default:
                    cx = x;
                    cy = y;
                    break;
            }

            if (child.isComment) {
              this.g.setColor(Color.BLACK);
                Font f = this.g.getFont();
              Font commentFont = f.deriveFont(f.getStyle(), f.getSize()/2);
                this.g.setFont(commentFont);
                cx = x1;
                cy = y2 + oH/2;
                this.g.drawString(child.text, cx, cy);
            }
            else {
                //for deleting background of child
                //we need the bounds at the actual positions
                childBounds = getTextBounds(child.text, cx, cy, g
                        , rendererModel.getZoomFactor());
                this.g.setColor(textGroup.backColor!=null ? textGroup.backColor : this.rendererModel.getBackColor());
                Rectangle2D childBackground = new Rectangle2D.Double(cx,
                        cy - childBounds.getHeight(), childBounds.getWidth(),
                        childBounds.getHeight());
                this.g.fill(childBackground);

              this.g.setColor(textGroup.color);
              //write child
              this.g.drawString(child.text, cx, cy);
              if (child.subscript != null) {
                  int scx = (int)(cx + (childBounds.getWidth() * 0.75));
                  int scy = (int)(cy + (childBounds.getHeight() / 3));
                  Font f = this.g.getFont();   // TODO : move to font manager
                  Font subscriptFont = f.deriveFont(f.getStyle(), f.getSize() - 2);
                  this.g.setFont(subscriptFont);
                  this.g.setColor(textGroup.color);
                  //write subscript
                  this.g.drawString(child.subscript, scx, scy);
              }
            }
        }
        if(textGroup.isNotTypeableUnderlined){
            this.g.setColor(Color.RED);
            this.g.drawLine(x1,y2,x2,y2);
        }
    }

    public void visit(IRenderingElement element) {
        Color savedColor = this.g.getColor();
        if (element instanceof ElementGroup)
            visit((ElementGroup) element);
        else if (element instanceof WedgeLineElement)
            visit((WedgeLineElement) element);
        else if (element instanceof WigglyLineElement)
            visit((WigglyLineElement) element);
        else if (element instanceof LineElement)
            visit((LineElement) element);
        else if (element instanceof ArrowElement)
            visit((ArrowElement) element);
        else if (element instanceof OvalElement)
            visit((OvalElement) element);
        else if (element instanceof TextGroupElement)
            visit((TextGroupElement) element);
        else if (element instanceof AtomSymbolElement)
            visit((AtomSymbolElement) element);
        else if (element instanceof TextElement)
            visit((TextElement) element);
        else if (element instanceof RectangleElement)
            visit((RectangleElement) element);
        else if (element instanceof PathElement)
            visit((PathElement) element);
        else if (element instanceof GeneralPath)
            visit((GeneralPath)element);
        else if (element instanceof Bounds) {
            // ignore
        } else
            System.err.println("Visitor method for "
                    + element.getClass().getName() + " is not implemented");
        this.g.setColor(savedColor);
    }

    /**
     * The font manager must be set by any renderer that uses this class!
     */
    public void setFontManager(IFontManager fontManager) {
        this.fontManager = (AWTFontManager) fontManager;
    }

    public void setRendererModel(JChemPaintRendererModel rendererModel) {
        this.rendererModel = rendererModel;
        if (rendererModel.getUseAntiAliasing()) {
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
           
//            g.setStroke(new BasicStroke((int)rendererModel.getBondWidth()));
        }
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
                           RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
                           RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                           RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                           RenderingHints.VALUE_STROKE_NORMALIZE);
       
    }
}
TOP

Related Classes of org.openscience.jchempaint.renderer.visitor.AWTDrawVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.