jdk/src/share/classes/sun/font/LayoutPathImpl.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * (C) Copyright IBM Corp. 2005, All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
package sun.font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
//
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
// This is the 'simple' mapping implementation.  It does things the most
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
// straightforward way even if that is a bit slow.  It won't
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
// handle complex paths efficiently, and doesn't handle closed paths.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
//
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.awt.Shape;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.awt.font.LayoutPath;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.awt.geom.AffineTransform;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.awt.geom.GeneralPath;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.awt.geom.NoninvertibleTransformException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.awt.geom.PathIterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.awt.geom.Point2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.util.Formatter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import static java.awt.geom.PathIterator.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import static java.lang.Math.abs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import static java.lang.Math.sqrt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
public abstract class LayoutPathImpl extends LayoutPath {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    // Convenience APIs
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    public Point2D pointToPath(double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
        Point2D.Double pt = new Point2D.Double(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
        pointToPath(pt, pt);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
        return pt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    public Point2D pathToPoint(double a, double o, boolean preceding) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
        Point2D.Double pt = new Point2D.Double(a, o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
        pathToPoint(pt, preceding, pt);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
        return pt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    public void pointToPath(double x, double y, Point2D pt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
        pt.setLocation(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
        pointToPath(pt, pt);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    public void pathToPoint(double a, double o, boolean preceding, Point2D pt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
        pt.setLocation(a, o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
        pathToPoint(pt, preceding, pt);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    // extra utility APIs
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    public abstract double start();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    public abstract double end();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    public abstract double length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    public abstract Shape mapShape(Shape s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    // debugging flags
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    private static final boolean LOGMAP = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    private static final Formatter LOG = new Formatter(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
     * Indicate how positions past the start and limit of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
     * path are treated.  PINNED adjusts these positions so
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
     * as to be within start and limit.  EXTENDED ignores the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * start and limit and effectively extends the first and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * last segments of the path 'infinitely'.  CLOSED wraps
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     * positions around the ends of the path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    public static enum EndType {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        PINNED, EXTENDED, CLOSED;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        public boolean isPinned() { return this == PINNED; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        public boolean isExtended() { return this == EXTENDED; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        public boolean isClosed() { return this == CLOSED; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    // Top level construction.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * Return a path representing the path from the origin through the points in order.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    public static LayoutPathImpl getPath(EndType etype, double ... coords) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        if ((coords.length & 0x1) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
            throw new IllegalArgumentException("odd number of points not allowed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        return SegmentPath.get(etype, coords);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * Use to build a SegmentPath.  This takes the data and preanalyzes it for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * information that the SegmentPath needs, then constructs a SegmentPath
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     * from that.  Mainly, this lets SegmentPath cache the lengths along
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     * the path to each line segment, and so avoid calculating them over and over.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    public static final class SegmentPathBuilder {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        private double[] data;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        private int w;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        private double px;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        private double py;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        private double a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        private boolean pconnect;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
         * Construct a SegmentPathBuilder.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        public SegmentPathBuilder() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
         * Reset the builder for a new path.  Datalen is a hint of how many
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
         * points will be in the path, and the working buffer will be sized
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
         * to accomodate at least this number of points.  If datalen is zero,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
         * the working buffer is freed (it will be allocated on first use).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        public void reset(int datalen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            if (data == null || datalen > data.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                data = new double[datalen];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            } else if (datalen == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                data = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            w = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            px = py = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            pconnect = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
         * Automatically build from a list of points represented by pairs of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
         * doubles.  Initial advance is zero.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        public SegmentPath build(EndType etype, double... pts) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
            assert(pts.length % 2 == 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
            reset(pts.length / 2 * 3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            for (int i = 0; i < pts.length; i += 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                nextPoint(pts[i], pts[i+1], i != 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            return complete(etype);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
         * Move to a new point.  If there is no data, this will become the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
         * first point.  If there is data, and the previous call was a lineTo, this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
         * point is checked against the previous point, and if different, this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
         * starts a new segment at the same advance as the end of the last
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
         * segment.  If there is data, and the previous call was a moveTo, this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
         * replaces the point used for that previous call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
         * Calling this is optional, lineTo will suffice and the initial point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
         * will be set to 0, 0.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        public void moveTo(double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
            nextPoint(x, y, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
         * Connect to a new point.  If there is no data, the previous point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
         * is presumed to be 0, 0.  This point is checked against
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
         * the previous point, and if different, this point is added to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
         * the path and the advance extended.  If this point is the same as the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
         * previous point, the path remains unchanged.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        public void lineTo(double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            nextPoint(x, y, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
         * Add a new point, and increment advance if connect is true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
         * This automatically rejects duplicate points and multiple disconnected points.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        private void nextPoint(double x, double y, boolean connect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
            // if zero length move or line, ignore
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            if (x == px && y == py) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            if (w == 0) { // this is the first point, make sure we have space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                if (data == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                    data = new double[6];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                if (connect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                    w = 3; // default first point to 0, 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            // if multiple disconnected move, just update position, leave advance alone
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            if (w != 0 && !connect && !pconnect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                data[w-3] = px = x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                data[w-2] = py = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            // grow data to deal with new point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            if (w == data.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                double[] t = new double[w * 2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                System.arraycopy(data, 0, t, 0, w);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                data = t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            if (connect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                double dx = x - px;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                double dy = y - py;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                a += sqrt(dx * dx + dy * dy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            // update data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            data[w++] = x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            data[w++] = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
            data[w++] = a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            // update state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            px = x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            py = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            pconnect = connect;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        public SegmentPath complete() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            return complete(EndType.EXTENDED);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
         * Complete building a SegmentPath.  Once this is called, the builder is restored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
         * to its initial state and information about the previous path is released.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
         * end type indicates whether to treat the path as closed, extended, or pinned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        public SegmentPath complete(EndType etype) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            SegmentPath result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            if (data == null || w < 6) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            if (w == data.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                result = new SegmentPath(data, etype);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                reset(0); // releases pointer to data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
                double[] dataToAdopt = new double[w];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                System.arraycopy(data, 0, dataToAdopt, 0, w);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                result = new SegmentPath(dataToAdopt, etype);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                reset(2); // reuses data, since we held on to it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * Represents a path built from segments.  Each segment is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     * represented by a triple: x, y, and cumulative advance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * These represent the end point of the segment.  The start
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     * point of the first segment is represented by the triple
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * at position 0.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     * The path might have breaks in it, e.g. it is not connected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     * These will be represented by pairs of triplets that share the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     * same advance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * The path might be extended, pinned, or closed.  If extended,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * the initial and final segments are considered to extend
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     * 'indefinitely' past the bounds of the advance.  If pinned,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * they end at the bounds of the advance.  If closed,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     * advances before the start or after the end 'wrap around' the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     * path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
     * The start of the path is the initial triple.  This provides
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
     * the nominal advance at the given x, y position (typically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
     * zero).  The end of the path is the final triple.  This provides
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
     * the advance at the end, the total length of the path is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     * thus the ending advance minus the starting advance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
     * Note: We might want to cache more auxiliary data than the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     * advance, but this seems adequate for now.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    public static final class SegmentPath extends LayoutPathImpl {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        private double[] data; // triplets x, y, a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        EndType etype;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        public static SegmentPath get(EndType etype, double... pts) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            return new SegmentPathBuilder().build(etype, pts);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
         * Internal, use SegmentPathBuilder or one of the static
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
         * helper functions to construct a SegmentPath.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        SegmentPath(double[] data, EndType etype) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
            this.data = data;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
            this.etype = etype;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        // LayoutPath API
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        public void pathToPoint(Point2D location, boolean preceding, Point2D point) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            locateAndGetIndex(location, preceding, point);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        // the path consists of line segments, which i'll call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        // 'path vectors'.  call each run of path vectors a 'path segment'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        // no path vector in a path segment is zero length (in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        // data, such vectors start a new path segment).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        // for each path segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        // for each path vector...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        // we look at the dot product of the path vector and the vector from the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        // origin of the path vector to the test point.  if <0 (case
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        // A), the projection of the test point is before the start of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        // the path vector.  if > the square of the length of the path vector
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        // (case B), the projection is past the end point of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        // path vector.  otherwise (case C), it lies on the path vector.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        // determine the closeset point on the path vector.  if case A, it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        // is the start of the path vector.  if case B and this is the last
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        // path vector in the path segment, it is the end of the path vector.  If
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        // case C, it is the projection onto the path vector.  Otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
        // there is no closest point.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
        // if we have a closest point, compare the distance from it to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        // the test point against our current closest distance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        // (culling should be fast, currently i am using distance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        // squared, but there's probably better ways).  if we're
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        // closer, save the new point as the current closest point,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        // and record the path vector index so we can determine the final
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        // info if this turns out to be the closest point in the end.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
        // after we have processed all the segments we will have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        // tested each path vector and each endpoint.  if our point is not on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        // an endpoint, we're done; we can compute the position and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        // offset again, or if we saved it off we can just use it.  if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        // we're on an endpoint we need to see which path vector we should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        // associate with.  if we're at the start or end of a path segment,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        // we're done-- the first or last vector of the segment is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        // one we associate with.  we project against that vector to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        // get the offset, and pin to that vector to get the length.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        // otherwise, we compute the information as follows.  if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        // dot product (see above) with the following vector is zero,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        // we associate with that vector.  otherwise, if the dot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        // product with the previous vector is zero, we associate with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        // that vector.  otherwise we're beyond the end of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        // previous vector and before the start of the current vector.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        // we project against both vectors and get the distance from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        // the test point to the projection (this will be the offset).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
        // if they are the same, we take the following vector.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        // otherwise use the vector from which the test point is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        // _farthest_ (this is because the point lies most clearly in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        // the half of the plane defined by extending that vector).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        // the returned position is the path length to the (possibly
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        // pinned) point, the offset is the projection onto the line
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        // along the vector, and we have a boolean flag which if false
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        // indicates that we associate with the previous vector at a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        // junction (which is necessary when projecting such a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        // location back to a point).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        public boolean pointToPath(Point2D pt, Point2D result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            double x = pt.getX();               // test point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            double y = pt.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            double bx = data[0];                // previous point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            double by = data[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            double bl = data[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            // start with defaults
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
            double cd2 = Double.MAX_VALUE;       // current best distance from path, squared
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            double cx = 0;                       // current best x
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            double cy = 0;                       // current best y
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            double cl = 0;                       // current best position along path
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
            int ci = 0;                          // current best index into data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
            for (int i = 3; i < data.length; i += 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                double nx = data[i];             // current end point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                double ny = data[i+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                double nl = data[i+2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                double dx = nx - bx;             // vector from previous to current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                double dy = ny - by;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                double dl = nl - bl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                double px = x - bx;              // vector from previous to test point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                double py = y - by;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
                // determine sign of dot product of vectors from bx, by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                // if < 0, we're before the start of this vector
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                double dot = dx * px + dy * py;      // dot product
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                double vcx, vcy, vcl;                // hold closest point on vector as x, y, l
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                int vi;                              // hold index of line, is data.length if last point on path
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                do {                                 // use break below, lets us avoid initializing vcx, vcy...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                    if (dl == 0 ||                   // moveto, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                        (dot < 0 &&                  // before path vector and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                         (!etype.isExtended() ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
                          i != 3))) {                // closest point is start of vector
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                        vcx = bx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
                        vcy = by;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
                        vcl = bl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                        vi = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                        double l2 = dl * dl;         // aka dx * dx + dy * dy, square of length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                        if (dot <= l2 ||             // closest point is not past end of vector, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                            (etype.isExtended() &&   // we're extended and at the last segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                             i == data.length - 3)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                            double p = dot / l2;     // get parametric along segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                            vcx = bx + p * dx;       // compute closest point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                            vcy = by + p * dy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                            vcl = bl + p * dl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                            vi = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                            if (i == data.length - 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                                vcx = nx;            // special case, always test last point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                                vcy = ny;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                                vcl = nl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                                vi = data.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                                break;               // typical case, skip point, we'll pick it up next iteration
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                    double tdx = x - vcx;        // compute distance from (usually pinned) projection to test point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                    double tdy = y - vcy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                    double td2 = tdx * tdx + tdy * tdy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
                    if (td2 <= cd2) {            // new closest point, record info on it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                        cd2 = td2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                        cx = vcx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                        cy = vcy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                        cl = vcl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                        ci = vi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                } while (false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                bx = nx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                by = ny;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                bl = nl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
            // we have our closest point, get the info
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
            bx = data[ci-3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
            by = data[ci-2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
            if (cx != bx || cy != by) {     // not on endpoint, no need to resolve
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                double nx = data[ci];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                double ny = data[ci+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                double co = sqrt(cd2);     // have a true perpendicular, so can use distance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                if ((x-cx)*(ny-by) > (y-cy)*(nx-bx)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                    co = -co;              // determine sign of offset
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                result.setLocation(cl, co);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            } else {                        // on endpoint, we need to resolve which segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                boolean havePrev = ci != 3 && data[ci-1] != data[ci-4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                boolean haveFoll = ci != data.length && data[ci-1] != data[ci+2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                boolean doExtend = etype.isExtended() && (ci == 3 || ci == data.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                if (havePrev && haveFoll) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                    Point2D.Double pp = new Point2D.Double(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                    calcoffset(ci - 3, doExtend, pp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                    Point2D.Double fp = new Point2D.Double(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                    calcoffset(ci, doExtend, fp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                    if (abs(pp.y) > abs(fp.y)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
                        result.setLocation(pp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                        return true; // associate with previous
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
                        result.setLocation(fp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                        return false; // associate with following
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                } else if (havePrev) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
                    result.setLocation(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                    calcoffset(ci - 3, doExtend, result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                    result.setLocation(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                    calcoffset(ci, doExtend, result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
         * Return the location of the point passed in result as mapped to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
         * line indicated by index.  If doExtend is true, extend the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
         * x value without pinning to the ends of the line.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
         * this assumes that index is valid and references a line that has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
         * non-zero length.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        private void calcoffset(int index, boolean doExtend, Point2D result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            double bx = data[index-3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            double by = data[index-2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            double px = result.getX() - bx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
            double py = result.getY() - by;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
            double dx = data[index] - bx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
            double dy = data[index+1] - by;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            double l = data[index+2] - data[index - 1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            // rx = A dot B / |B|
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
            // ry = A dot invB / |B|
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
            double rx = (px * dx + py * dy) / l;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
            double ry = (px * -dy + py * dx) / l;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            if (!doExtend) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                if (rx < 0) rx = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
                else if (rx > l) rx = l;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
            rx += data[index-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            result.setLocation(rx, ry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        // LayoutPathImpl API
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        public Shape mapShape(Shape s) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            return new Mapper().mapShape(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        public double start() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
            return data[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        public double end() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
            return data[data.length - 1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        public double length() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
            return data[data.length-1] - data[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        // Utilities
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
         * Get the 'modulus' of an advance on a closed path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        private double getClosedAdvance(double a, boolean preceding) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
            if (etype.isClosed()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                a -= data[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                int count = (int)(a/length());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                a -= count * length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                if (a < 0 || (a == 0 && preceding)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                    a += length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                a += data[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            return a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
         * Return the index of the segment associated with advance. This
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
         * points to the start of the triple and is a multiple of 3 between
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
         * 3 and data.length-3 inclusive.  It never points to a 'moveto' triple.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
         * If the path is closed, 'a' is mapped to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
         * a value between the start and end of the path, inclusive.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
         * If preceding is true, and 'a' lies on a segment boundary,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
         * return the index of the preceding segment, else return the index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
         * of the current segment (if it is not a moveto segment) otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
         * the following segment (which is never a moveto segment).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
         * Note: if the path is not closed, the advance might not actually
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
         * lie on the returned segment-- it might be before the first, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
         * after the last.  The first or last segment (as appropriate)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
         * will be returned in this case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        private int getSegmentIndexForAdvance(double a, boolean preceding) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
            // must have local advance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            a = getClosedAdvance(a, preceding);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            // note we must avoid 'moveto' segments.  the first segment is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            // always a moveto segment, so we always skip it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            int i, lim;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            for (i = 5, lim = data.length-1; i < lim; i += 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                double v = data[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                if (a < v || (a == v && preceding)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            return i-2; // adjust to start of segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
         * Map a location based on the provided segment, returning in pt.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
         * Seg must be a valid 'lineto' segment.  Note: if the path is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
         * closed, x must be within the start and end of the path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        private void map(int seg, double a, double o, Point2D pt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            double dx = data[seg] - data[seg-3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            double dy = data[seg+1] - data[seg-2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
            double dl = data[seg+2] - data[seg-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            double ux = dx/dl; // could cache these, but is it worth it?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
            double uy = dy/dl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
            a -= data[seg-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
            pt.setLocation(data[seg-3] + a * ux - o * uy,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                           data[seg-2] + a * uy + o * ux);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
         * Map the point, and return the segment index.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        private int locateAndGetIndex(Point2D loc, boolean preceding, Point2D result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            double a = loc.getX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            double o = loc.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            int seg = getSegmentIndexForAdvance(a, preceding);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            map(seg, a, o, result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            return seg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        // Mapping classes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        // Map the path onto each path segment.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        // Record points where the advance 'enters' and 'exits' the path segment, and connect successive
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        // points when appropriate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
         * This represents a line segment from the iterator.  Each target segment will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
         * interpret it, and since this process needs slope along the line
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
         * segment, this lets us compute it once and pass it around easily.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        class LineInfo {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
            double sx, sy; // start
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
            double lx, ly; // limit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
            double m;      // slope dy/dx
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
             * Set the lineinfo to this line
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            void set(double sx, double sy, double lx, double ly) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                this.sx = sx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                this.sy = sy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                this.lx = lx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                this.ly = ly;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                double dx = lx - sx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                if (dx == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    m = 0; // we'll check for this elsewhere
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                    double dy = ly - sy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                    m = dy / dx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            void set(LineInfo rhs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
                this.sx = rhs.sx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                this.sy = rhs.sy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                this.lx = rhs.lx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
                this.ly = rhs.ly;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                this.m  = rhs.m;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
             * Return true if we intersect the infinitely tall rectangle with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
             * lo <= x < hi.  If we do, also return the pinned portion of ourselves in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
             * result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            boolean pin(double lo, double hi, LineInfo result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
                result.set(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                if (lx >= sx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                    if (sx < hi && lx >= lo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                        if (sx < lo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                            if (m != 0) result.sy = sy + m * (lo - sx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                            result.sx = lo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                        if (lx > hi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                            if (m != 0) result.ly = ly + m * (hi - lx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                            result.lx = hi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                    if (lx < hi && sx >= lo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                        if (lx < lo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                            if (m != 0) result.ly = ly + m * (lo - lx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                            result.lx = lo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                        if (sx > hi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                            if (m != 0) result.sy = sy + m * (hi - sx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                            result.sx = hi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
             * Return true if we intersect the segment at ix.  This takes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
             * the path end type into account and computes the relevant
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
             * parameters to pass to pin(double, double, LineInfo).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
            boolean pin(int ix, LineInfo result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                double lo = data[ix-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                double hi = data[ix+2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                switch (SegmentPath.this.etype) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                case PINNED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                case EXTENDED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                    if (ix == 3) lo = Double.NEGATIVE_INFINITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                    if (ix == data.length - 3) hi = Double.POSITIVE_INFINITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                case CLOSED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
                    // not implemented
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                return pin(lo, hi, result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
         * Each segment will construct its own general path, mapping the provided lines
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
         * into its own simple space.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        class Segment {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
            final int ix;        // index into data array for this segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            final double ux, uy; // unit vector
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
            final LineInfo temp; // working line info
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
            boolean broken;      // true if a moveto has occurred since we last added to our path
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
            double cx, cy;       // last point in gp
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
            GeneralPath gp;      // path built for this segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
            Segment(int ix) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
                this.ix = ix;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                double len = data[ix+2] - data[ix-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
                this.ux = (data[ix] - data[ix-3]) / len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
                this.uy = (data[ix+1] - data[ix-2]) / len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
                this.temp = new LineInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
            void init() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
                if (LOGMAP) LOG.format("s(%d) init\n", ix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
                broken = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
                cx = cy = Double.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                this.gp = new GeneralPath();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            void move() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
                if (LOGMAP) LOG.format("s(%d) move\n", ix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
                broken = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            void close() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                if (!broken) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                    if (LOGMAP) LOG.format("s(%d) close\n[cp]\n", ix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
                    gp.closePath();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
            void line(LineInfo li) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
                if (LOGMAP) LOG.format("s(%d) line %g, %g to %g, %g\n", ix, li.sx, li.sy, li.lx, li.ly);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
                if (li.pin(ix, temp)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
                    if (LOGMAP) LOG.format("pin: %g, %g to %g, %g\n", temp.sx, temp.sy, temp.lx, temp.ly);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
                    temp.sx -= data[ix-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
                    double sx = data[ix-3] + temp.sx * ux - temp.sy * uy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
                    double sy = data[ix-2] + temp.sx * uy + temp.sy * ux;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
                    temp.lx -= data[ix-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                    double lx = data[ix-3] + temp.lx * ux - temp.ly * uy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                    double ly = data[ix-2] + temp.lx * uy + temp.ly * ux;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                    if (LOGMAP) LOG.format("points: %g, %g to %g, %g\n", sx, sy, lx, ly);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                    if (sx != cx || sy != cy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                        if (broken) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
                            if (LOGMAP) LOG.format("[mt %g, %g]\n", sx, sy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
                            gp.moveTo((float)sx, (float)sy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
                            if (LOGMAP) LOG.format("[lt %g, %g]\n", sx, sy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                            gp.lineTo((float)sx, (float)sy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
                    if (LOGMAP) LOG.format("[lt %g, %g]\n", lx, ly);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
                    gp.lineTo((float)lx, (float)ly);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                    broken = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
                    cx = lx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
                    cy = ly;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
        class Mapper {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
            final LineInfo li;                 // working line info
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
            final ArrayList<Segment> segments; // cache additional data on segments, working objects
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
            final Point2D.Double mpt;          // last moveto source point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
            final Point2D.Double cpt;          // current source point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            boolean haveMT;                    // true when last op was a moveto
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
            Mapper() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                li = new LineInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                segments = new ArrayList<Segment>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
                for (int i = 3; i < data.length; i += 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                    if (data[i+2] != data[i-1]) { // a new segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
                        segments.add(new Segment(i));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                mpt = new Point2D.Double();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
                cpt = new Point2D.Double();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
            void init() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
                if (LOGMAP) LOG.format("init\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
                haveMT = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
                for (Segment s: segments) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                    s.init();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
            void moveTo(double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
                if (LOGMAP) LOG.format("moveto %g, %g\n", x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
                mpt.x = x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
                mpt.y = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
                haveMT = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
            void lineTo(double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
                if (LOGMAP) LOG.format("lineto %g, %g\n", x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
                if (haveMT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
                    // prepare previous point for no-op check
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
                    cpt.x = mpt.x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
                    cpt.y = mpt.y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
                if (x == cpt.x && y == cpt.y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
                    // lineto is a no-op
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
                if (haveMT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                    // current point is the most recent moveto point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                    haveMT = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
                    for (Segment s: segments) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
                        s.move();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
                li.set(cpt.x, cpt.y, x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
                for (Segment s: segments) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
                    s.line(li);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
                cpt.x = x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
                cpt.y = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
            void close() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
                if (LOGMAP) LOG.format("close\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
                lineTo(mpt.x, mpt.y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
                for (Segment s: segments) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
                    s.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
            public Shape mapShape(Shape s) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
                if (LOGMAP) LOG.format("mapshape on path: %s\n", LayoutPathImpl.SegmentPath.this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
                PathIterator pi = s.getPathIterator(null, 1); // cheap way to handle curves.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
                if (LOGMAP) LOG.format("start\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
                init();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
                final double[] coords = new double[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
                while (!pi.isDone()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
                    switch (pi.currentSegment(coords)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
                    case SEG_CLOSE: close(); break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
                    case SEG_MOVETO: moveTo(coords[0], coords[1]); break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
                    case SEG_LINETO: lineTo(coords[0], coords[1]); break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
                    default: break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
                    pi.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
                if (LOGMAP) LOG.format("finish\n\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
                GeneralPath gp = new GeneralPath();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
                for (Segment seg: segments) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
                    gp.append(seg.gp, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
                return gp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
        // for debugging
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
        public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
            StringBuilder b = new StringBuilder();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
            b.append("{");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
            b.append(etype.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
            b.append(" ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
            for (int i = 0; i < data.length; i += 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
                if (i > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
                    b.append(",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
                float x = ((int)(data[i] * 100))/100.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
                float y = ((int)(data[i+1] * 100))/100.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
                float l = ((int)(data[i+2] * 10))/10.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
                b.append("{");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
                b.append(x);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
                b.append(",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
                b.append(y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
                b.append(",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
                b.append(l);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
                b.append("}");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
            b.append("}");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            return b.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
    public static class EmptyPath extends LayoutPathImpl {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
        private AffineTransform tx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
        public EmptyPath(AffineTransform tx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
            this.tx = tx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
        public void pathToPoint(Point2D location, boolean preceding, Point2D point) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
            if (tx != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
                tx.transform(location, point);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
                point.setLocation(location);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
        public boolean pointToPath(Point2D pt, Point2D result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
            result.setLocation(pt);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
            if (tx != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
                    tx.inverseTransform(pt, result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
                catch (NoninvertibleTransformException ex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
            return result.getX() > 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
        public double start() { return 0; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
        public double end() { return 0; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
        public double length() { return 0; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
        public Shape mapShape(Shape s) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
            if (tx != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
                return tx.createTransformedShape(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
            return s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
}