diff options
Diffstat (limited to 'libjava/classpath/java/awt/BasicStroke.java')
-rw-r--r-- | libjava/classpath/java/awt/BasicStroke.java | 902 |
1 files changed, 0 insertions, 902 deletions
diff --git a/libjava/classpath/java/awt/BasicStroke.java b/libjava/classpath/java/awt/BasicStroke.java deleted file mode 100644 index eac69d9..0000000 --- a/libjava/classpath/java/awt/BasicStroke.java +++ /dev/null @@ -1,902 +0,0 @@ -/* BasicStroke.java -- - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath 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 -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt; - -import gnu.java.awt.java2d.CubicSegment; -import gnu.java.awt.java2d.LineSegment; -import gnu.java.awt.java2d.QuadSegment; -import gnu.java.awt.java2d.Segment; - -import java.awt.geom.FlatteningPathIterator; -import java.awt.geom.GeneralPath; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.util.Arrays; - -/** - * A general purpose {@link Stroke} implementation that can represent a wide - * variety of line styles for use with subclasses of {@link Graphics2D}. - * <p> - * The line cap and join styles can be set using the options illustrated - * here: - * <p> - * <img src="doc-files/capjoin.png" width="350" height="180" - * alt="Illustration of line cap and join styles" /> - * <p> - * A dash array can be used to specify lines with alternating opaque and - * transparent sections. - */ -public class BasicStroke implements Stroke -{ - /** - * Indicates a mitered line join style. See the class overview for an - * illustration. - */ - public static final int JOIN_MITER = 0; - - /** - * Indicates a rounded line join style. See the class overview for an - * illustration. - */ - public static final int JOIN_ROUND = 1; - - /** - * Indicates a bevelled line join style. See the class overview for an - * illustration. - */ - public static final int JOIN_BEVEL = 2; - - /** - * Indicates a flat line cap style. See the class overview for an - * illustration. - */ - public static final int CAP_BUTT = 0; - - /** - * Indicates a rounded line cap style. See the class overview for an - * illustration. - */ - public static final int CAP_ROUND = 1; - - /** - * Indicates a square line cap style. See the class overview for an - * illustration. - */ - public static final int CAP_SQUARE = 2; - - /** The stroke width. */ - private final float width; - - /** The line cap style. */ - private final int cap; - - /** The line join style. */ - private final int join; - - /** The miter limit. */ - private final float limit; - - /** The dash array. */ - private final float[] dash; - - /** The dash phase. */ - private final float phase; - - // The inner and outer paths of the stroke - private Segment start, end; - - /** - * Creates a new <code>BasicStroke</code> instance with the given attributes. - * - * @param width the line width (>= 0.0f). - * @param cap the line cap style (one of {@link #CAP_BUTT}, - * {@link #CAP_ROUND} or {@link #CAP_SQUARE}). - * @param join the line join style (one of {@link #JOIN_ROUND}, - * {@link #JOIN_BEVEL}, or {@link #JOIN_MITER}). - * @param miterlimit the limit to trim the miter join. The miterlimit must be - * greater than or equal to 1.0f. - * @param dash The array representing the dashing pattern. There must be at - * least one non-zero entry. - * @param dashPhase is negative and dash is not null. - * - * @throws IllegalArgumentException If one input parameter doesn't meet - * its needs. - */ - public BasicStroke(float width, int cap, int join, float miterlimit, - float[] dash, float dashPhase) - { - if (width < 0.0f ) - throw new IllegalArgumentException("width " + width + " < 0"); - else if (cap < CAP_BUTT || cap > CAP_SQUARE) - throw new IllegalArgumentException("cap " + cap + " out of range [" - + CAP_BUTT + ".." + CAP_SQUARE + "]"); - else if (miterlimit < 1.0f && join == JOIN_MITER) - throw new IllegalArgumentException("miterlimit " + miterlimit - + " < 1.0f while join == JOIN_MITER"); - else if (join < JOIN_MITER || join > JOIN_BEVEL) - throw new IllegalArgumentException("join " + join + " out of range [" - + JOIN_MITER + ".." + JOIN_BEVEL - + "]"); - else if (dashPhase < 0.0f && dash != null) - throw new IllegalArgumentException("dashPhase " + dashPhase - + " < 0.0f while dash != null"); - else if (dash != null) - if (dash.length == 0) - throw new IllegalArgumentException("dash.length is 0"); - else - { - boolean allZero = true; - - for ( int i = 0; i < dash.length; ++i) - { - if (dash[i] != 0.0f) - { - allZero = false; - break; - } - } - - if (allZero) - throw new IllegalArgumentException("all dashes are 0.0f"); - } - - this.width = width; - this.cap = cap; - this.join = join; - limit = miterlimit; - this.dash = dash == null ? null : (float[]) dash.clone(); - phase = dashPhase; - } - - /** - * Creates a new <code>BasicStroke</code> instance with the given attributes. - * - * @param width the line width (>= 0.0f). - * @param cap the line cap style (one of {@link #CAP_BUTT}, - * {@link #CAP_ROUND} or {@link #CAP_SQUARE}). - * @param join the line join style (one of {@link #JOIN_ROUND}, - * {@link #JOIN_BEVEL}, or {@link #JOIN_MITER}). - * @param miterlimit the limit to trim the miter join. The miterlimit must be - * greater than or equal to 1.0f. - * - * @throws IllegalArgumentException If one input parameter doesn't meet - * its needs. - */ - public BasicStroke(float width, int cap, int join, float miterlimit) - { - this(width, cap, join, miterlimit, null, 0); - } - - /** - * Creates a new <code>BasicStroke</code> instance with the given attributes. - * The miter limit defaults to <code>10.0</code>. - * - * @param width the line width (>= 0.0f). - * @param cap the line cap style (one of {@link #CAP_BUTT}, - * {@link #CAP_ROUND} or {@link #CAP_SQUARE}). - * @param join the line join style (one of {@link #JOIN_ROUND}, - * {@link #JOIN_BEVEL}, or {@link #JOIN_MITER}). - * - * @throws IllegalArgumentException If one input parameter doesn't meet - * its needs. - */ - public BasicStroke(float width, int cap, int join) - { - this(width, cap, join, 10, null, 0); - } - - /** - * Creates a new <code>BasicStroke</code> instance with the given line - * width. The default values are: - * <ul> - * <li>line cap style: {@link #CAP_SQUARE};</li> - * <li>line join style: {@link #JOIN_MITER};</li> - * <li>miter limit: <code>10.0f</code>. - * </ul> - * - * @param width the line width (>= 0.0f). - * - * @throws IllegalArgumentException If <code>width</code> is negative. - */ - public BasicStroke(float width) - { - this(width, CAP_SQUARE, JOIN_MITER, 10, null, 0); - } - - /** - * Creates a new <code>BasicStroke</code> instance. The default values are: - * <ul> - * <li>line width: <code>1.0f</code>;</li> - * <li>line cap style: {@link #CAP_SQUARE};</li> - * <li>line join style: {@link #JOIN_MITER};</li> - * <li>miter limit: <code>10.0f</code>. - * </ul> - */ - public BasicStroke() - { - this(1, CAP_SQUARE, JOIN_MITER, 10, null, 0); - } - - /** - * Creates a shape representing the stroked outline of the given shape. - * THIS METHOD IS NOT YET IMPLEMENTED. - * - * @param s the shape. - */ - public Shape createStrokedShape(Shape s) - { - PathIterator pi = s.getPathIterator(null); - - if( dash == null ) - return solidStroke( pi ); - - return dashedStroke( pi ); - } - - /** - * Returns the line width. - * - * @return The line width. - */ - public float getLineWidth() - { - return width; - } - - /** - * Returns a code indicating the line cap style (one of {@link #CAP_BUTT}, - * {@link #CAP_ROUND}, {@link #CAP_SQUARE}). - * - * @return A code indicating the line cap style. - */ - public int getEndCap() - { - return cap; - } - - /** - * Returns a code indicating the line join style (one of {@link #JOIN_BEVEL}, - * {@link #JOIN_MITER} or {@link #JOIN_ROUND}). - * - * @return A code indicating the line join style. - */ - public int getLineJoin() - { - return join; - } - - /** - * Returns the miter limit. - * - * @return The miter limit. - */ - public float getMiterLimit() - { - return limit; - } - - /** - * Returns the dash array, which defines the length of alternate opaque and - * transparent sections in lines drawn with this stroke. If - * <code>null</code>, a continuous line will be drawn. - * - * @return The dash array (possibly <code>null</code>). - */ - public float[] getDashArray() - { - return dash; - } - - /** - * Returns the dash phase for the stroke. This is the offset from the start - * of a path at which the pattern defined by {@link #getDashArray()} is - * rendered. - * - * @return The dash phase. - */ - public float getDashPhase() - { - return phase; - } - - /** - * Returns the hash code for this object. The hash is calculated by - * xoring the hash, cap, join, limit, dash array and phase values - * (converted to <code>int</code> first with - * <code>Float.floatToIntBits()</code> if the value is a - * <code>float</code>). - * - * @return The hash code. - */ - public int hashCode() - { - int hash = Float.floatToIntBits(width); - hash ^= cap; - hash ^= join; - hash ^= Float.floatToIntBits(limit); - - if (dash != null) - for (int i = 0; i < dash.length; i++) - hash ^= Float.floatToIntBits(dash[i]); - - hash ^= Float.floatToIntBits(phase); - - return hash; - } - - /** - * Compares this <code>BasicStroke</code> for equality with an arbitrary - * object. This method returns <code>true</code> if and only if: - * <ul> - * <li><code>o</code> is an instanceof <code>BasicStroke</code>;</li> - * <li>this object has the same width, line cap style, line join style, - * miter limit, dash array and dash phase as <code>o</code>.</li> - * </ul> - * - * @param o the object (<code>null</code> permitted). - * - * @return <code>true</code> if this stroke is equal to <code>o</code> and - * <code>false</code> otherwise. - */ - public boolean equals(Object o) - { - if (! (o instanceof BasicStroke)) - return false; - BasicStroke s = (BasicStroke) o; - return width == s.width && cap == s.cap && join == s.join - && limit == s.limit && Arrays.equals(dash, s.dash) && phase == s.phase; - } - - private Shape solidStroke(PathIterator pi) - { - double[] coords = new double[6]; - double x, y, x0, y0; - boolean pathOpen = false; - GeneralPath output = new GeneralPath( ); - Segment[] p; - x = x0 = y = y0 = 0; - - while( !pi.isDone() ) - { - switch( pi.currentSegment(coords) ) - { - case PathIterator.SEG_MOVETO: - x0 = x = coords[0]; - y0 = y = coords[1]; - if( pathOpen ) - { - capEnds(); - convertPath(output, start); - start = end = null; - pathOpen = false; - } - break; - - case PathIterator.SEG_LINETO: - p = (new LineSegment(x, y, coords[0], coords[1])). - getDisplacedSegments(width/2.0); - if( !pathOpen ) - { - start = p[0]; - end = p[1]; - pathOpen = true; - } - else - addSegments(p); - - x = coords[0]; - y = coords[1]; - break; - - case PathIterator.SEG_QUADTO: - p = (new QuadSegment(x, y, coords[0], coords[1], coords[2], - coords[3])).getDisplacedSegments(width/2.0); - if( !pathOpen ) - { - start = p[0]; - end = p[1]; - pathOpen = true; - } - else - addSegments(p); - - x = coords[2]; - y = coords[3]; - break; - - case PathIterator.SEG_CUBICTO: - p = new CubicSegment(x, y, coords[0], coords[1], - coords[2], coords[3], - coords[4], coords[5]).getDisplacedSegments(width/2.0); - if( !pathOpen ) - { - start = p[0]; - end = p[1]; - pathOpen = true; - } - else - addSegments(p); - - x = coords[4]; - y = coords[5]; - break; - - case PathIterator.SEG_CLOSE: - if (x == x0 && y == y0) - { - joinSegments(new Segment[] { start.first, end.first }); - } - else - { - p = (new LineSegment(x, y, x0, y0)).getDisplacedSegments(width / 2.0); - addSegments(p); - } - convertPath(output, start); - convertPath(output, end); - start = end = null; - pathOpen = false; - output.setWindingRule(GeneralPath.WIND_EVEN_ODD); - break; - } - pi.next(); - } - - if( pathOpen ) - { - capEnds(); - convertPath(output, start); - } - return output; - } - - private Shape dashedStroke(PathIterator pi) - { - // The choice of (flatnessSq == width / 3) is made to be consistent with - // the flattening in CubicSegment.getDisplacedSegments - FlatteningPathIterator flat = new FlatteningPathIterator(pi, - Math.sqrt(width / 3)); - - // Holds the endpoint of the current segment (or piece of a segment) - double[] coords = new double[2]; - - // Holds end of the last segment - double x, y, x0, y0; - x = x0 = y = y0 = 0; - - // Various useful flags - boolean pathOpen = false; - boolean dashOn = true; - boolean offsetting = (phase != 0); - - // How far we are into the current dash - double distance = 0; - int dashIndex = 0; - - // And variables to hold the final output - GeneralPath output = new GeneralPath(); - Segment[] p; - - // Iterate over the FlatteningPathIterator - while (! flat.isDone()) - { - switch (flat.currentSegment(coords)) - { - case PathIterator.SEG_MOVETO: - x0 = x = coords[0]; - y0 = y = coords[1]; - - if (pathOpen) - { - capEnds(); - convertPath(output, start); - start = end = null; - pathOpen = false; - } - - break; - - case PathIterator.SEG_LINETO: - boolean segmentConsumed = false; - - while (! segmentConsumed) - { - // Find the total remaining length of this segment - double segLength = Math.sqrt((x - coords[0]) * (x - coords[0]) - + (y - coords[1]) - * (y - coords[1])); - boolean spanBoundary = true; - double[] segmentEnd = null; - - // The current segment fits entirely inside the current dash - if ((offsetting && distance + segLength <= phase) - || distance + segLength <= dash[dashIndex]) - { - spanBoundary = false; - } - - // Otherwise, we need to split the segment in two, as this - // segment spans a dash boundry - else - { - segmentEnd = (double[]) coords.clone(); - - // Calculate the remaining distance in this dash, - // and coordinates of the dash boundary - double reqLength; - if (offsetting) - reqLength = phase - distance; - else - reqLength = dash[dashIndex] - distance; - - coords[0] = x + ((coords[0] - x) * reqLength / segLength); - coords[1] = y + ((coords[1] - y) * reqLength / segLength); - } - - if (offsetting || ! dashOn) - { - // Dash is off, or we are in offset - treat this as a - // moveTo - x0 = x = coords[0]; - y0 = y = coords[1]; - - if (pathOpen) - { - capEnds(); - convertPath(output, start); - start = end = null; - pathOpen = false; - } - } - else - { - // Dash is on - treat this as a lineTo - p = (new LineSegment(x, y, coords[0], coords[1])).getDisplacedSegments(width / 2.0); - - if (! pathOpen) - { - start = p[0]; - end = p[1]; - pathOpen = true; - } - else - addSegments(p); - - x = coords[0]; - y = coords[1]; - } - - // Update variables depending on whether we spanned a - // dash boundary or not - if (! spanBoundary) - { - distance += segLength; - segmentConsumed = true; - } - else - { - if (offsetting) - offsetting = false; - dashOn = ! dashOn; - distance = 0; - coords = segmentEnd; - - if (dashIndex + 1 == dash.length) - dashIndex = 0; - else - dashIndex++; - - // Since the value of segmentConsumed is still false, - // the next run of the while loop will complete the segment - } - } - break; - - // This is a flattened path, so we don't need to deal with curves - } - flat.next(); - } - - if (pathOpen) - { - capEnds(); - convertPath(output, start); - } - return output; - } - - /** - * Cap the ends of the path (joining the start and end list of segments) - */ - private void capEnds() - { - Segment returnPath = end.last; - - end.reverseAll(); // reverse the path. - end = null; - capEnd(start, returnPath); - start.last = returnPath.last; - end = null; - - capEnd(start, start); - } - - /** - * Append the Segments in s to the GeneralPath p - */ - private void convertPath(GeneralPath p, Segment s) - { - Segment v = s; - p.moveTo((float)s.P1.getX(), (float)s.P1.getY()); - - do - { - if(v instanceof LineSegment) - p.lineTo((float)v.P2.getX(), (float)v.P2.getY()); - else if(v instanceof QuadSegment) - p.quadTo((float)((QuadSegment)v).cp.getX(), - (float)((QuadSegment)v).cp.getY(), - (float)v.P2.getX(), - (float)v.P2.getY()); - else if(v instanceof CubicSegment) - p.curveTo((float)((CubicSegment)v).cp1.getX(), - (float)((CubicSegment)v).cp1.getY(), - (float)((CubicSegment)v).cp2.getX(), - (float)((CubicSegment)v).cp2.getY(), - (float)v.P2.getX(), - (float)v.P2.getY()); - v = v.next; - } while(v != s && v != null); - - p.closePath(); - } - - /** - * Add the segments to start and end (the inner and outer edges of the stroke) - */ - private void addSegments(Segment[] segments) - { - joinSegments(segments); - start.add(segments[0]); - end.add(segments[1]); - } - - private void joinSegments(Segment[] segments) - { - double[] p0 = start.last.cp2(); - double[] p1 = new double[]{start.last.P2.getX(), start.last.P2.getY()}; - double[] p2 = new double[]{segments[0].first.P1.getX(), segments[0].first.P1.getY()}; - double[] p3 = segments[0].cp1(); - Point2D p; - - p = lineIntersection(p0[0],p0[1],p1[0],p1[1], - p2[0],p2[1],p3[0],p3[1], false); - - double det = (p1[0] - p0[0])*(p3[1] - p2[1]) - - (p3[0] - p2[0])*(p1[1] - p0[1]); - - if( det > 0 ) - { - // start and segment[0] form the 'inner' part of a join, - // connect the overlapping segments - joinInnerSegments(start, segments[0], p); - joinOuterSegments(end, segments[1], p); - } - else - { - // end and segment[1] form the 'inner' part - joinInnerSegments(end, segments[1], p); - joinOuterSegments(start, segments[0], p); - } - } - - /** - * Make a cap between a and b segments, - * where a-->b is the direction of iteration. - */ - private void capEnd(Segment a, Segment b) - { - double[] p0, p1; - double dx, dy, l; - Point2D c1,c2; - - switch( cap ) - { - case CAP_BUTT: - a.add(new LineSegment(a.last.P2, b.P1)); - break; - - case CAP_SQUARE: - p0 = a.last.cp2(); - p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()}; - dx = p1[0] - p0[0]; - dy = p1[1] - p0[1]; - l = Math.sqrt(dx * dx + dy * dy); - dx = 0.5*width*dx/l; - dy = 0.5*width*dy/l; - c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy); - c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy); - a.add(new LineSegment(a.last.P2, c1)); - a.add(new LineSegment(c1, c2)); - a.add(new LineSegment(c2, b.P1)); - break; - - case CAP_ROUND: - p0 = a.last.cp2(); - p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()}; - dx = p1[0] - p0[0]; - dy = p1[1] - p0[1]; - if (dx != 0 && dy != 0) - { - l = Math.sqrt(dx * dx + dy * dy); - dx = (2.0/3.0)*width*dx/l; - dy = (2.0/3.0)*width*dy/l; - } - - c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy); - c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy); - a.add(new CubicSegment(a.last.P2, c1, c2, b.P1)); - break; - } - a.add(b); - } - - /** - * Returns the intersection of two lines, or null if there isn't one. - * @param infinite - true if the lines should be regarded as infinite, false - * if the intersection must be within the given segments. - * @return a Point2D or null. - */ - private Point2D lineIntersection(double X1, double Y1, - double X2, double Y2, - double X3, double Y3, - double X4, double Y4, - boolean infinite) - { - double x1 = X1; - double y1 = Y1; - double rx = X2 - x1; - double ry = Y2 - y1; - - double x2 = X3; - double y2 = Y3; - double sx = X4 - x2; - double sy = Y4 - y2; - - double determinant = sx * ry - sy * rx; - double nom = (sx * (y2 - y1) + sy * (x1 - x2)); - - // lines can be considered parallel. - if (Math.abs(determinant) < 1E-6) - return null; - - nom = nom / determinant; - - // check if lines are within the bounds - if(!infinite && (nom > 1.0 || nom < 0.0)) - return null; - - return new Point2D.Double(x1 + nom * rx, y1 + nom * ry); - } - - /** - * Join a and b segments, where a-->b is the direction of iteration. - * - * insideP is the inside intersection point of the join, needed for - * calculating miter lengths. - */ - private void joinOuterSegments(Segment a, Segment b, Point2D insideP) - { - double[] p0, p1; - double dx, dy, l; - Point2D c1,c2; - - switch( join ) - { - case JOIN_MITER: - p0 = a.last.cp2(); - p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()}; - double[] p2 = new double[]{b.P1.getX(), b.P1.getY()}; - double[] p3 = b.cp1(); - Point2D p = lineIntersection(p0[0],p0[1],p1[0],p1[1],p2[0],p2[1],p3[0],p3[1], true); - if( p == null || insideP == null ) - a.add(new LineSegment(a.last.P2, b.P1)); - else if((p.distance(insideP)/width) < limit) - { - a.add(new LineSegment(a.last.P2, p)); - a.add(new LineSegment(p, b.P1)); - } - else - { - // outside miter limit, do a bevel join. - a.add(new LineSegment(a.last.P2, b.P1)); - } - break; - - case JOIN_ROUND: - p0 = a.last.cp2(); - p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()}; - dx = p1[0] - p0[0]; - dy = p1[1] - p0[1]; - l = Math.sqrt(dx * dx + dy * dy); - dx = 0.5*width*dx/l; - dy = 0.5*width*dy/l; - c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy); - - p0 = new double[]{b.P1.getX(), b.P1.getY()}; - p1 = b.cp1(); - - dx = p0[0] - p1[0]; // backwards direction. - dy = p0[1] - p1[1]; - l = Math.sqrt(dx * dx + dy * dy); - dx = 0.5*width*dx/l; - dy = 0.5*width*dy/l; - c2 = new Point2D.Double(p0[0] + dx, p0[1] + dy); - a.add(new CubicSegment(a.last.P2, c1, c2, b.P1)); - break; - - case JOIN_BEVEL: - a.add(new LineSegment(a.last.P2, b.P1)); - break; - } - } - - /** - * Join a and b segments, removing any overlap - */ - private void joinInnerSegments(Segment a, Segment b, Point2D p) - { - double[] p0 = a.last.cp2(); - double[] p1 = new double[] { a.last.P2.getX(), a.last.P2.getY() }; - double[] p2 = new double[] { b.P1.getX(), b.P1.getY() }; - double[] p3 = b.cp1(); - - if (p == null) - { - // Dodgy. - a.add(new LineSegment(a.last.P2, b.P1)); - p = new Point2D.Double((b.P1.getX() + a.last.P2.getX()) / 2.0, - (b.P1.getY() + a.last.P2.getY()) / 2.0); - } - else - // This assumes segments a and b are single segments, which is - // incorrect - if they are a linked list of segments (ie, passed in - // from a flattening operation), this produces strange results!! - a.last.P2 = b.P1 = p; - } -} |