/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * The MCT platform is licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ /** * */ package plotter; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; /** * Stores painting operations so they can be tested. * @author Adam Crume */ public class CountingGraphics extends GraphicsProxy { private final CountingGraphics root; private List<Line2D> lines = new ArrayList<Line2D>(); private int points; private int simpleLines; private int polyLines; private int shapes; /** * Creates a counting graphics context. * @param base graphics context to forward painting operations to */ public CountingGraphics(Graphics2D base) { super(base); this.root = this; } private CountingGraphics(Graphics2D base, CountingGraphics root) { super(base); this.root = root; } @Override public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) { super.drawPolyline(xPoints, yPoints, nPoints); root.points += nPoints; root.polyLines++; AffineTransform transform = base.getTransform(); for(int i = 1; i < nPoints; i++) { Point2D p1 = transform.transform(new Point2D.Double(xPoints[i - 1], yPoints[i - 1]), null); Point2D p2 = transform.transform(new Point2D.Double(xPoints[i], yPoints[i]), null); root.lines.add(new Line2D.Double(p1, p2)); } } @Override public void drawLine(int x1, int y1, int x2, int y2) { super.drawLine(x1, y1, x2, y2); root.points += 2; root.simpleLines++; AffineTransform transform = base.getTransform(); Point2D p1 = transform.transform(new Point2D.Double(x1, y1), null); Point2D p2 = transform.transform(new Point2D.Double(x2, y2), null); root.lines.add(new Line2D.Double(p1, p2)); } @Override public void draw(Shape s) { super.draw(s); root.shapes++; PathIterator pi = s.getPathIterator(base.getTransform(), 0.5); float[] points = new float[6]; Point2D p1 = null; Point2D cp = null; while(!pi.isDone()) { switch(pi.currentSegment(points)) { case PathIterator.SEG_MOVETO: { root.points++; double x1 = Math.floor(points[0]); double y1 = Math.floor(points[1]); p1 = new Point2D.Double(x1, y1); cp = p1; break; } case PathIterator.SEG_LINETO: { root.points++; double x2 = Math.floor(points[0]); double y2 = Math.floor(points[1]); Point2D p2 = new Point2D.Double(x2, y2); root.lines.add(new Line2D.Double(p1, p2)); p1 = p2; break; } case PathIterator.SEG_CLOSE: { root.points++; root.lines.add(new Line2D.Double(p1, cp)); p1 = cp; break; } } pi.next(); } } @Override public Graphics create() { return new CountingGraphics((Graphics2D) base.create(), root); } @Override public Graphics create(int x, int y, int width, int height) { return new CountingGraphics((Graphics2D) base.create(x, y, width, height), root); } /** * Returns the line segments that were drawn. * This includes calls to {@link #drawLine(int, int, int, int)} and {@link #drawPolyline(int[], int[], int)}. * With polylines, each individual line segment is added separately. * @return the line segments that were drawn */ public List<Line2D> getLines() { return lines; } /** * Returns the total point count. * This is increased by 2 for each call to {@link #drawLine(int, int, int, int)}, and by <code>n</code> for each call to {@link #drawPolyline(int[], int[], int)}, * where <code>n</code> is the last parameter. * @return number of points */ public int getPointCount() { return points; } /** * Returns the number of calls to {@link #draw(Shape)}. * @return number of {@link Shape}s drawn */ public int getShapeCount() { return shapes; } }