KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > geom > QuadCurve2D


1 /*
2  * @(#)QuadCurve2D.java 1.29 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.geom;
9
10 import java.awt.Shape JavaDoc;
11 import java.awt.Rectangle JavaDoc;
12
13 /**
14  * The <code>QuadCurve2D</code> class defines a quadratic parametric curve
15  * segment in (x,&nbsp;y) coordinate space.
16  * <p>
17  * This class is only the abstract superclass for all objects that
18  * store a 2D quadratic curve segment.
19  * The actual storage representation of the coordinates is left to
20  * the subclass.
21  *
22  * @version 1.29, 12/19/03
23  * @author Jim Graham
24  */

25 public abstract class QuadCurve2D implements Shape JavaDoc, Cloneable JavaDoc {
26     /**
27      * A quadratic parametric curve segment specified with
28      * <code>float</code> coordinates.
29      */

30
31     public static class Float extends QuadCurve2D JavaDoc {
32
33     /**
34      * The x coordinate of the start point of the quadratic curve
35          * segment.
36      */

37     public float x1;
38
39     /**
40      * The y coordinate of the start point of the quadratic curve
41          * segment.
42      */

43     public float y1;
44
45     /**
46      * The x coordinate of the control point of the quadratic curve
47          * segment.
48      */

49     public float ctrlx;
50
51     /**
52      * The y coordinate of the control point of the quadratic curve
53          * segment.
54      */

55     public float ctrly;
56
57     /**
58      * The x coordinate of the end point of the quadratic curve
59          * segment.
60      */

61     public float x2;
62
63     /**
64      * The y coordinate of the end point of the quadratic curve
65          * segment.
66      */

67     public float y2;
68
69     /**
70      * Constructs and initializes a <code>QuadCurve2D</code> with
71          * coordinates (0, 0, 0, 0, 0, 0).
72      */

73     public Float() {
74     }
75
76     /**
77      * Constructs and initializes a <code>QuadCurve2D</code> from the
78          * specified coordinates.
79          * @param x1,&nbsp;y1 the starting point coordinates
80          * @param ctrlx,&nbsp;ctrly the coordinates of the control point
81          * @param x2,&nbsp;y2 the ending point coordinates
82      */

83     public Float(float x1, float y1,
84              float ctrlx, float ctrly,
85              float x2, float y2) {
86         setCurve(x1, y1, ctrlx, ctrly, x2, y2);
87     }
88
89     /**
90      * Returns the x coordinate of the start point in
91          * <code>double</code> precision.
92          * @return the x coordinate of the starting point.
93      */

94     public double getX1() {
95         return (double) x1;
96     }
97
98     /**
99      * Returns the y coordinate of the start point in
100          * <code>double</code> precision.
101          * @return the y coordinate of the starting point.
102      */

103     public double getY1() {
104         return (double) y1;
105     }
106
107     /**
108      * Returns the start point.
109          * @return a {@link Point2D} object that is the starting point
110          * of this <code>QuadCurve2D</code>.
111      */

112     public Point2D JavaDoc getP1() {
113         return new Point2D.Float JavaDoc(x1, y1);
114     }
115
116     /**
117      * Returns the x coordinate of the control point in
118          * <code>double</code> precision.
119          * @return the x coordinate of the control point.
120      */

121     public double getCtrlX() {
122         return (double) ctrlx;
123     }
124
125     /**
126      * Returns the y coordinate of the control point in
127          * <code>double</code> precision.
128          * @return the y coordiante of the control point.
129      */

130     public double getCtrlY() {
131         return (double) ctrly;
132     }
133
134     /**
135      * Returns the control point.
136          * @return a <code>Point2D</code> that is the control point of
137          * this <code>QuadCurve2D</code>.
138      */

139     public Point2D JavaDoc getCtrlPt() {
140         return new Point2D.Float JavaDoc(ctrlx, ctrly);
141     }
142
143     /**
144      * Returns the x coordinate of the end point in
145          * <code>double</code> precision.
146          * @return the x coordinate of the end point.
147      */

148     public double getX2() {
149         return (double) x2;
150     }
151
152     /**
153      * Returns the y coordinate of the end point in
154          * <code>double</code> precision.
155          * @return the y coordiante of the end point.
156      */

157     public double getY2() {
158         return (double) y2;
159     }
160
161     /**
162      * Returns the end point.
163          * @return a <code>Point2D</code> that is the end point of this
164          * <code>QuadCurve2D</code>.
165      */

166     public Point2D JavaDoc getP2() {
167         return new Point2D.Float JavaDoc(x2, y2);
168     }
169
170     /**
171      * Sets the location of the endpoints and controlpoint of this
172          * <code>QuadCurve2D</code> to the specified <code>double</code>
173          * coordinates.
174          * @param x1,&nbsp;y1 the coordinates of the starting point
175          * @param ctrlx,&nbsp;ctrly the coordinates of the control point
176          * @param x2,&nbsp;y2 the coordinates of the ending point
177      */

178     public void setCurve(double x1, double y1,
179                  double ctrlx, double ctrly,
180                  double x2, double y2) {
181         this.x1 = (float) x1;
182         this.y1 = (float) y1;
183         this.ctrlx = (float) ctrlx;
184         this.ctrly = (float) ctrly;
185         this.x2 = (float) x2;
186         this.y2 = (float) y2;
187     }
188
189     /**
190      * Sets the location of the endpoints and controlpoint of this curve
191      * to the specified <code>float</code> coordinates.
192          * @param x1,&nbsp;y1 the coordinates of the starting point
193          * @param ctrlx,&nbsp;ctrly the coordinates of the control point
194          * @param x2,&nbsp;y2 the coordinates of the ending point
195      */

196     public void setCurve(float x1, float y1,
197                  float ctrlx, float ctrly,
198                  float x2, float y2) {
199         this.x1 = x1;
200         this.y1 = y1;
201         this.ctrlx = ctrlx;
202         this.ctrly = ctrly;
203         this.x2 = x2;
204         this.y2 = y2;
205     }
206
207     /**
208      * Returns the bounding box of this <code>QuadCurve2D</code>.
209          * @return a {@link Rectangle2D} that is the bounding box
210          * of the shape of this <code>QuadCurve2D</code>.
211      */

212     public Rectangle2D JavaDoc getBounds2D() {
213         float left = Math.min(Math.min(x1, x2), ctrlx);
214         float top = Math.min(Math.min(y1, y2), ctrly);
215         float right = Math.max(Math.max(x1, x2), ctrlx);
216         float bottom = Math.max(Math.max(y1, y2), ctrly);
217         return new Rectangle2D.Float JavaDoc(left, top,
218                      right - left, bottom - top);
219     }
220     }
221
222     /**
223      * A quadratic parametric curve segment specified with
224      * <code>double</code> coordinates.
225      */

226     public static class Double extends QuadCurve2D JavaDoc {
227     /**
228      * The x coordinate of the start point of the quadratic curve
229          * segment.
230      */

231     public double x1;
232
233     /**
234      * The x coordinate of the start point of the quadratic curve
235          * segment.
236      */

237     public double y1;
238
239     /**
240      * The x coordinate of the control point of the quadratic curve
241          * segment.
242      */

243     public double ctrlx;
244
245     /**
246      * The y coordinate of the control point of the quadratic curve
247          * segment.
248      */

249     public double ctrly;
250
251     /**
252      * The x coordinate of the end point of the quadratic curve
253          * segment.
254      */

255     public double x2;
256
257     /**
258      * The y coordinate of the end point of the quadratic curve
259          * segment.
260      */

261     public double y2;
262
263     /**
264      * Constructs and initializes a <code>QuadCurve2D</code> with
265          * coordinates (0, 0, 0, 0, 0, 0).
266      */

267     public Double() {
268     }
269
270     /**
271      * Constructs and initializes a <code>QuadCurve2D</code> from the
272          * specified coordinates.
273          * @param x1,&nbsp;y1 the coordinates of the starting point
274          * @param ctrlx,&nbsp;ctrly the coordinates of the control point
275          * @param x2,&nbsp;y2 the coordinates of the ending point
276      */

277     public Double(double x1, double y1,
278               double ctrlx, double ctrly,
279               double x2, double y2) {
280         setCurve(x1, y1, ctrlx, ctrly, x2, y2);
281     }
282
283     /**
284      * Returns the x coordinate of the start point in
285          * <code>double</code> precision.
286          * @return the x coordinate of the starting point.
287      */

288     public double getX1() {
289         return x1;
290     }
291
292     /**
293      * Returns the y coordinate of the start point in
294          * <code>double</code> precision.
295          * @return the y coordiante of the starting point.
296      */

297     public double getY1() {
298         return y1;
299     }
300
301     /**
302      * Returns the start point.
303          * @return a <code>Point2D</code> that is the starting point
304          * of this <code>QuadCurve2D</code>.
305      */

306     public Point2D JavaDoc getP1() {
307         return new Point2D.Double JavaDoc(x1, y1);
308     }
309
310     /**
311      * Returns the x coordinate of the control point in
312          * <code>double</code> precision.
313          * @return the x coordinate of the control point.
314      */

315     public double getCtrlX() {
316         return ctrlx;
317     }
318
319     /**
320      * Returns the y coordinate of the control point in
321          * <code>double</code> precision.
322          * @return the y coordiante of the control point.
323      */

324     public double getCtrlY() {
325         return ctrly;
326     }
327
328     /**
329      * Returns the control point.
330          * @return a <code>Point2D</code> object that is the control
331          * point of this <code>QuadCurve2D</code>.
332      */

333     public Point2D JavaDoc getCtrlPt() {
334         return new Point2D.Double JavaDoc(ctrlx, ctrly);
335     }
336
337     /**
338      * Returns the x coordinate of the end point in
339          * <code>double</code> precision.
340          * @return the x coordiante of the end point.
341      */

342     public double getX2() {
343         return x2;
344     }
345
346     /**
347      * Returns the y coordinate of the end point in
348          * <code>double</code> precision.
349          * @return the y coordiante of the end point.
350      */

351     public double getY2() {
352         return y2;
353     }
354
355     /**
356      * Returns the end point.
357          * @return a <code>Point2D</code> that is the end point
358          * of this <code>QuadCurve2D</code>.
359      */

360     public Point2D JavaDoc getP2() {
361         return new Point2D.Double JavaDoc(x2, y2);
362     }
363
364     /**
365      * Sets the location of the endpoints and controlpoint of this curve
366      * to the specified <code>double</code> coordinates.
367          * @param x1,&nbsp;y1 the coordinates of the starting point
368          * @param ctrlx,&nbsp;ctrly the coordinates of the control point
369          * @param x2,&nbsp;y2 the coordinates of the ending point
370      */

371     public void setCurve(double x1, double y1,
372                  double ctrlx, double ctrly,
373                  double x2, double y2) {
374         this.x1 = x1;
375         this.y1 = y1;
376         this.ctrlx = ctrlx;
377         this.ctrly = ctrly;
378         this.x2 = x2;
379         this.y2 = y2;
380     }
381
382     /**
383      * Returns the bounding box of this <code>QuadCurve2D</code>.
384          * @return a <code>Rectangle2D</code> that is the bounding
385          * box of the shape of this <code>QuadCurve2D</code>.
386      */

387     public Rectangle2D JavaDoc getBounds2D() {
388         double left = Math.min(Math.min(x1, x2), ctrlx);
389         double top = Math.min(Math.min(y1, y2), ctrly);
390         double right = Math.max(Math.max(x1, x2), ctrlx);
391         double bottom = Math.max(Math.max(y1, y2), ctrly);
392         return new Rectangle2D.Double JavaDoc(left, top,
393                       right - left, bottom - top);
394     }
395     }
396
397     /**
398      * This is an abstract class that cannot be instantiated directly.
399      * Type-specific implementation subclasses are available for
400      * instantiation and provide a number of formats for storing
401      * the information necessary to satisfy the various accessor
402      * methods below.
403      *
404      * @see java.awt.geom.QuadCurve2D.Float
405      * @see java.awt.geom.QuadCurve2D.Double
406      */

407     protected QuadCurve2D() {
408     }
409
410     /**
411      * Returns the x coordinate of the start point in
412      * <code>double</code> in precision.
413      * @return the x coordinate of the start point.
414      */

415     public abstract double getX1();
416
417     /**
418      * Returns the y coordinate of the start point in
419      * <code>double</code> precision.
420      * @return the y coordinate of the start point.
421      */

422     public abstract double getY1();
423
424     /**
425      * Returns the start point.
426      * @return a <code>Point2D</code> that is the start point of this
427      * <code>QuadCurve2D</code>.
428      */

429     public abstract Point2D JavaDoc getP1();
430
431     /**
432      * Returns the x coordinate of the control point in
433      * <code>double</code> precision.
434      * @return x coordinate the control point
435      */

436     public abstract double getCtrlX();
437
438     /**
439      * Returns the y coordinate of the control point in
440      * <code>double</code> precision.
441      * @return the y coordinate of the control point.
442      */

443     public abstract double getCtrlY();
444
445     /**
446      * Returns the control point.
447      * @return a <code>Point2D</code> that is the control point of this
448      * <code>Point2D</code>.
449      */

450     public abstract Point2D JavaDoc getCtrlPt();
451
452     /**
453      * Returns the x coordinate of the end point in
454      * <code>double</code> precision.
455      * @return the x coordiante of the end point.
456      */

457     public abstract double getX2();
458
459     /**
460      * Returns the y coordinate of the end point in
461      * <code>double</code> precision.
462      * @return the y coordinate of the end point.
463      */

464     public abstract double getY2();
465
466     /**
467      * Returns the end point.
468      * @return a <code>Point</code> object that is the end point
469      * of this <code>Point2D</code>.
470      */

471     public abstract Point2D JavaDoc getP2();
472
473     /**
474      * Sets the location of the endpoints and controlpoint of this curve
475      * to the specified <code>double</code> coordinates.
476      * @param x1,&nbsp;y1 the coordinates of the starting point
477      * @param ctrlx,&nbsp;ctrly the coordinates of the control point
478      * @param x2,&nbsp;y2 the coordinates of the ending point
479      */

480     public abstract void setCurve(double x1, double y1,
481                   double ctrlx, double ctrly,
482                   double x2, double y2);
483
484     /**
485      * Sets the location of the endpoints and controlpoints of this
486      * <code>QuadCurve2D</code> to the <code>double</code> coordinates at
487      * the specified offset in the specified array.
488      * @param coords the array containing coordinate values
489      * @param offset the index into the array from which to start
490      * getting the coordinate values and assigning them to this
491      * <code>QuadCurve2D</code>
492      */

493     public void setCurve(double[] coords, int offset) {
494     setCurve(coords[offset + 0], coords[offset + 1],
495          coords[offset + 2], coords[offset + 3],
496          coords[offset + 4], coords[offset + 5]);
497     }
498
499     /**
500      * Sets the location of the endpoints and controlpoint of this
501      * <code>QuadCurve2D</code> to the specified <code>Point2D</code>
502      * coordinates.
503      * @param p1 the starting point
504      * @param cp the control point
505      * @param p2 the ending point
506      */

507     public void setCurve(Point2D JavaDoc p1, Point2D JavaDoc cp, Point2D JavaDoc p2) {
508     setCurve(p1.getX(), p1.getY(),
509          cp.getX(), cp.getY(),
510          p2.getX(), p2.getY());
511     }
512
513     /**
514      * Sets the location of the endpoints and controlpoints of this
515      * <code>QuadCurve2D</code> to the coordinates of the
516      * <code>Point2D</code> objects at the specified offset in
517      * the specified array.
518      * @param pts an array containing <code>Point2D</code> that define
519      * coordinate values
520      * @param offset the index into <code>pts</code> at which to start
521      * getting the coordinate values and assigning them to this
522      * <code>QuadCurve2D</code>
523      */

524     public void setCurve(Point2D JavaDoc[] pts, int offset) {
525     setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(),
526          pts[offset + 1].getX(), pts[offset + 1].getY(),
527          pts[offset + 2].getX(), pts[offset + 2].getY());
528     }
529
530     /**
531      * Sets the location of the endpoints and controlpoint of this
532      * <code>QuadCurve2D</code> to the same as those in the specified
533      * <code>QuadCurve2D</code>.
534      * @param c the specified <code>QuadCurve2D</code>
535      */

536     public void setCurve(QuadCurve2D JavaDoc c) {
537     setCurve(c.getX1(), c.getY1(),
538          c.getCtrlX(), c.getCtrlY(),
539          c.getX2(), c.getY2());
540     }
541
542     /**
543      * Returns the square of the flatness, or maximum distance of a
544      * controlpoint from the line connecting the endpoints, of the
545      * quadratic curve specified by the indicated controlpoints.
546      * @param x1,&nbsp;y1 the coordinates of the starting point
547      * @param ctrlx,&nbsp;ctrly the coordinates of the control point
548      * @param x2,&nbsp;y2 the coordinates of the ending point
549      * @return the square of the flatness of the quadratic curve
550      * defined by the specified coordinates.
551      */

552     public static double getFlatnessSq(double x1, double y1,
553                        double ctrlx, double ctrly,
554                        double x2, double y2) {
555     return Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx, ctrly);
556     }
557
558     /**
559      * Returns the flatness, or maximum distance of a
560      * controlpoint from the line connecting the endpoints, of the
561      * quadratic curve specified by the indicated controlpoints.
562      * @param x1,&nbsp;y1 the coordinates of the starting point
563      * @param ctrlx,&nbsp;ctrly the coordinates of the control point
564      * @param x2,&nbsp;y2 the coordinates of the ending point
565      * @return the flatness of the quadratic curve defined by the
566      * specified coordinates.
567      */

568     public static double getFlatness(double x1, double y1,
569                      double ctrlx, double ctrly,
570                      double x2, double y2) {
571     return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
572     }
573
574     /**
575      * Returns the square of the flatness, or maximum distance of a
576      * controlpoint from the line connecting the endpoints, of the
577      * quadratic curve specified by the controlpoints stored in the
578      * indicated array at the indicated index.
579      * @param coords an array containing coordinate values
580      * @param offset the index into <code>coords</code> at which to
581      * to start getting the values from the array and
582      * assigning them to a quadratic curve
583      * @return the flatness of the quadratic curve that is defined by the
584      * values in the specified array at the specified index.
585      */

586     public static double getFlatnessSq(double coords[], int offset) {
587     return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1],
588                   coords[offset + 4], coords[offset + 5],
589                   coords[offset + 2], coords[offset + 3]);
590     }
591
592     /**
593      * Returns the flatness, or maximum distance of a
594      * controlpoint from the line connecting the endpoints, of the
595      * quadratic curve specified by the controlpoints stored in the
596      * indicated array at the indicated index.
597      * @param coords an array containing coordinate values
598      * @param offset the index into <code>coords</code> at which to
599      * start getting the coordinate values and assigning
600      * them to a quadratic curve
601      * @return the flatness of a quadratic curve defined by the
602      * specified array at the specified offset.
603      */

604     public static double getFlatness(double coords[], int offset) {
605     return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1],
606                 coords[offset + 4], coords[offset + 5],
607                 coords[offset + 2], coords[offset + 3]);
608     }
609
610     /**
611      * Returns the square of the flatness, or maximum distance of a
612      * controlpoint from the line connecting the endpoints, of this
613      * <code>QuadCurve2D</code>.
614      * @return the square of the flatness of this
615      * <code>QuadCurve2D</code>.
616      */

617     public double getFlatnessSq() {
618     return Line2D.ptSegDistSq(getX1(), getY1(),
619                   getX2(), getY2(),
620                   getCtrlX(), getCtrlY());
621     }
622
623     /**
624      * Returns the flatness, or maximum distance of a
625      * controlpoint from the line connecting the endpoints, of this
626      * <code>QuadCurve2D</code>.
627      * @return the flatness of this <code>QuadCurve2D</code>.
628      */

629     public double getFlatness() {
630     return Line2D.ptSegDist(getX1(), getY1(),
631                 getX2(), getY2(),
632                 getCtrlX(), getCtrlY());
633     }
634
635     /**
636      * Subdivides this <code>QuadCurve2D</code> and stores the resulting
637      * two subdivided curves into the <code>left</code> and
638      * <code>right</code> curve parameters.
639      * Either or both of the <code>left</code> and <code>right</code>
640      * objects can be the same as this <code>QuadCurve2D</code> or
641      * <code>null</code>.
642      * @param left the <code>QuadCurve2D</code> object for storing the
643      * left or first half of the subdivided curve
644      * @param right the <code>QuadCurve2D</code> object for storing the
645      * right or second half of the subdivided curve
646      */

647     public void subdivide(QuadCurve2D JavaDoc left, QuadCurve2D JavaDoc right) {
648     subdivide(this, left, right);
649     }
650
651     /**
652      * Subdivides the quadratic curve specified by the <code>src</code>
653      * parameter and stores the resulting two subdivided curves into the
654      * <code>left</code> and <code>right</code> curve parameters.
655      * Either or both of the <code>left</code> and <code>right</code>
656      * objects can be the same as the <code>src</code> object or
657      * <code>null</code>.
658      * @param src the quadratic curve to be subdivided
659      * @param left the <code>QuadCurve2D</code> object for storing the
660      * left or first half of the subdivided curve
661      * @param right the <code>QuadCurve2D</code> object for storing the
662      * right or second half of the subdivided curve
663      */

664     public static void subdivide(QuadCurve2D JavaDoc src,
665                  QuadCurve2D JavaDoc left,
666                  QuadCurve2D JavaDoc right) {
667     double x1 = src.getX1();
668     double y1 = src.getY1();
669     double ctrlx = src.getCtrlX();
670     double ctrly = src.getCtrlY();
671     double x2 = src.getX2();
672     double y2 = src.getY2();
673     double ctrlx1 = (x1 + ctrlx) / 2.0;
674     double ctrly1 = (y1 + ctrly) / 2.0;
675     double ctrlx2 = (x2 + ctrlx) / 2.0;
676     double ctrly2 = (y2 + ctrly) / 2.0;
677     ctrlx = (ctrlx1 + ctrlx2) / 2.0;
678     ctrly = (ctrly1 + ctrly2) / 2.0;
679     if (left != null) {
680         left.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx, ctrly);
681     }
682     if (right != null) {
683         right.setCurve(ctrlx, ctrly, ctrlx2, ctrly2, x2, y2);
684     }
685     }
686
687     /**
688      * Subdivides the quadratic curve specified by the coordinates
689      * stored in the <code>src</code> array at indices
690      * <code>srcoff</code> through <code>srcoff</code>&nbsp;+&nbsp;5
691      * and stores the resulting two subdivided curves into the two
692      * result arrays at the corresponding indices.
693      * Either or both of the <code>left</code> and <code>right</code>
694      * arrays can be <code>null</code> or a reference to the same array
695      * and offset as the <code>src</code> array.
696      * Note that the last point in the first subdivided curve is the
697      * same as the first point in the second subdivided curve. Thus,
698      * it is possible to pass the same array for <code>left</code> and
699      * <code>right</code> and to use offsets such that
700      * <code>rightoff</code> equals <code>leftoff</code> + 4 in order
701      * to avoid allocating extra storage for this common point.
702      * @param src the array holding the coordinates for the source curve
703      * @param srcoff the offset into the array of the beginning of the
704      * the 6 source coordinates
705      * @param left the array for storing the coordinates for the first
706      * half of the subdivided curve
707      * @param leftoff the offset into the array of the beginning of the
708      * the 6 left coordinates
709      * @param right the array for storing the coordinates for the second
710      * half of the subdivided curve
711      * @param rightoff the offset into the array of the beginning of the
712      * the 6 right coordinates
713      */

714     public static void subdivide(double src[], int srcoff,
715                  double left[], int leftoff,
716                  double right[], int rightoff) {
717     double x1 = src[srcoff + 0];
718     double y1 = src[srcoff + 1];
719     double ctrlx = src[srcoff + 2];
720     double ctrly = src[srcoff + 3];
721     double x2 = src[srcoff + 4];
722     double y2 = src[srcoff + 5];
723     if (left != null) {
724         left[leftoff + 0] = x1;
725         left[leftoff + 1] = y1;
726     }
727     if (right != null) {
728         right[rightoff + 4] = x2;
729         right[rightoff + 5] = y2;
730     }
731     x1 = (x1 + ctrlx) / 2.0;
732     y1 = (y1 + ctrly) / 2.0;
733     x2 = (x2 + ctrlx) / 2.0;
734     y2 = (y2 + ctrly) / 2.0;
735     ctrlx = (x1 + x2) / 2.0;
736     ctrly = (y1 + y2) / 2.0;
737     if (left != null) {
738         left[leftoff + 2] = x1;
739         left[leftoff + 3] = y1;
740         left[leftoff + 4] = ctrlx;
741         left[leftoff + 5] = ctrly;
742     }
743     if (right != null) {
744         right[rightoff + 0] = ctrlx;
745         right[rightoff + 1] = ctrly;
746         right[rightoff + 2] = x2;
747         right[rightoff + 3] = y2;
748     }
749     }
750
751     /**
752      * Solves the quadratic whose coefficients are in the <code>eqn</code>
753      * array and places the non-complex roots back into the same array,
754      * returning the number of roots. The quadratic solved is represented
755      * by the equation:
756      * <pre>
757      * eqn = {C, B, A};
758      * ax^2 + bx + c = 0
759      * </pre>
760      * A return value of <code>-1</code> is used to distinguish a constant
761      * equation, which might be always 0 or never 0, from an equation that
762      * has no zeroes.
763      * @param eqn the array that contains the quadratic coefficients
764      * @return the number of roots, or <code>-1</code> if the equation is
765      * a constant
766      */

767     public static int solveQuadratic(double eqn[]) {
768     return solveQuadratic(eqn, eqn);
769     }
770
771     /**
772      * Solves the quadratic whose coefficients are in the <code>eqn</code>
773      * array and places the non-complex roots into the <code>res</code>
774      * array, returning the number of roots.
775      * The quadratic solved is represented by the equation:
776      * <pre>
777      * eqn = {C, B, A};
778      * ax^2 + bx + c = 0
779      * </pre>
780      * A return value of <code>-1</code> is used to distinguish a constant
781      * equation, which might be always 0 or never 0, from an equation that
782      * has no zeroes.
783      * @param eqn the specified array of coefficients to use to solve
784      * the quadratic equation
785      * @param res the array that contains the non-complex roots
786      * resulting from the solution of the quadratic equation
787      * @return the number of roots, or <code>-1</code> if the equation is
788      * a constant.
789      */

790     public static int solveQuadratic(double eqn[], double res[]) {
791     double a = eqn[2];
792     double b = eqn[1];
793     double c = eqn[0];
794     int roots = 0;
795     if (a == 0.0) {
796         // The quadratic parabola has degenerated to a line.
797
if (b == 0.0) {
798         // The line has degenerated to a constant.
799
return -1;
800         }
801         res[roots++] = -c / b;
802     } else {
803         // From Numerical Recipes, 5.6, Quadratic and Cubic Equations
804
double d = b * b - 4.0 * a * c;
805         if (d < 0.0) {
806         // If d < 0.0, then there are no roots
807
return 0;
808         }
809         d = Math.sqrt(d);
810         // For accuracy, calculate one root using:
811
// (-b +/- d) / 2a
812
// and the other using:
813
// 2c / (-b +/- d)
814
// Choose the sign of the +/- so that b+d gets larger in magnitude
815
if (b < 0.0) {
816         d = -d;
817         }
818         double q = (b + d) / -2.0;
819         // We already tested a for being 0 above
820
res[roots++] = q / a;
821         if (q != 0.0) {
822         res[roots++] = c / q;
823         }
824     }
825     return roots;
826     }
827
828     /**
829      * Tests if a specified coordinate is inside the boundary of the
830      * shape of this <code>QuadCurve2D</code>.
831      * @param x,&nbsp;y the specified coordinates
832      * @return <code>true</code> if the specified coordinate is inside
833      * the boundary of the shape of this
834      * <code>QuadCurve2D</code>; <code>false</code> otherwise.
835      */

836     public boolean contains(double x, double y) {
837
838     double x1 = getX1();
839     double y1 = getY1();
840     double xc = getCtrlX();
841     double yc = getCtrlY();
842     double x2 = getX2();
843     double y2 = getY2();
844
845     /*
846      * We have a convex shape bounded by quad curve Pc(t)
847      * and ine Pl(t).
848      *
849      * P1 = (x1, y1) - start point of curve
850      * P2 = (x2, y2) - end point of curve
851      * Pc = (xc, yc) - control point
852      *
853      * Pq(t) = P1*(1 - t)^2 + 2*Pc*t*(1 - t) + P2*t^2 =
854      * = (P1 - 2*Pc + P2)*t^2 + 2*(Pc - P1)*t + P1
855      * Pl(t) = P1*(1 - t) + P2*t
856      * t = [0:1]
857      *
858      * P = (x, y) - point of interest
859      *
860      * Let's look at second derivative of quad curve equation:
861      *
862      * Pq''(t) = 2 * (P1 - 2 * Pc + P2) = Pq''
863      * It's constant vector.
864      *
865      * Let's draw a line through P to be parallel to this
866      * vector and find the intersection of the quad curve
867      * and the line.
868      *
869      * Pq(t) is point of intersection if system of equations
870      * below has the solution.
871      *
872      * L(s) = P + Pq''*s == Pq(t)
873      * Pq''*s + (P - Pq(t)) == 0
874      *
875      * | xq''*s + (x - xq(t)) == 0
876      * | yq''*s + (y - yq(t)) == 0
877      *
878      * This system has the solution if rank of its matrix equals to 1.
879      * That is, determinant of the matrix should be zero.
880      *
881      * (y - yq(t))*xq'' == (x - xq(t))*yq''
882      *
883      * Let's solve this equation with 't' variable.
884      * Also let kx = x1 - 2*xc + x2
885      * ky = y1 - 2*yc + y2
886      *
887      * t0q = (1/2)*((x - x1)*ky - (y - y1)*kx) /
888      * ((xc - x1)*ky - (yc - y1)*kx)
889      *
890      * Let's do the same for our line Pl(t):
891      *
892      * t0l = ((x - x1)*ky - (y - y1)*kx) /
893      * ((x2 - x1)*ky - (y2 - y1)*kx)
894      *
895      * It's easy to check that t0q == t0l. This fact means
896      * we can compute t0 only one time.
897      *
898      * In case t0 < 0 or t0 > 1, we have an intersections outside
899      * of shape bounds. So, P is definitely out of shape.
900      *
901      * In case t0 is inside [0:1], we should calculate Pq(t0)
902      * and Pl(t0). We have three points for now, and all of them
903      * lie on one line. So, we just need to detect, is our point
904      * of interest between points of intersections or not.
905      *
906      * If the denominator in the t0q and t0l equations is
907      * zero, then the points must be collinear and so the
908      * curve is degenerate and encloses no area. Thus the
909      * result is false.
910      */

911     double kx = x1 - 2 * xc + x2;
912     double ky = y1 - 2 * yc + y2;
913     double dx = x - x1;
914     double dy = y - y1;
915     double dxl = x2 - x1;
916     double dyl = y2 - y1;
917
918     double t0 = (dx * ky - dy * kx) / (dxl * ky - dyl * kx);
919     if (t0 < 0 || t0 > 1 || t0 != t0) {
920         return false;
921     }
922
923     double xb = kx * t0 * t0 + 2 * (xc - x1) * t0 + x1;
924     double yb = ky * t0 * t0 + 2 * (yc - y1) * t0 + y1;
925     double xl = dxl * t0 + x1;
926     double yl = dyl * t0 + y1;
927
928     return (x >= xb && x < xl) ||
929            (x >= xl && x < xb) ||
930            (y >= yb && y < yl) ||
931            (y >= yl && y < yb);
932     }
933
934     /**
935      * Tests if a specified <code>Point2D</code> is inside the boundary of
936      * the shape of this <code>QuadCurve2D</code>.
937      * @param p the specified <code>Point2D</code>
938      * @return <code>true</code> if the specified <code>Point2D</code> is
939      * inside the boundary of the shape of this
940      * <code>QuadCurve2D</code>.
941      */

942     public boolean contains(Point2D JavaDoc p) {
943     return contains(p.getX(), p.getY());
944     }
945
946     /*
947      * Fill an array with the coefficients of the parametric equation
948      * in t, ready for solving against val with solveQuadratic.
949      * We currently have:
950      * val = Py(t) = C1*(1-t)^2 + 2*CP*t*(1-t) + C2*t^2
951      * = C1 - 2*C1*t + C1*t^2 + 2*CP*t - 2*CP*t^2 + C2*t^2
952      * = C1 + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
953      * 0 = (C1 - val) + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
954      * 0 = C + Bt + At^2
955      * C = C1 - val
956      * B = 2*CP - 2*C1
957      * A = C1 - 2*CP + C2
958      */

959     private static void fillEqn(double eqn[], double val,
960                 double c1, double cp, double c2) {
961     eqn[0] = c1 - val;
962     eqn[1] = cp + cp - c1 - c1;
963     eqn[2] = c1 - cp - cp + c2;
964     return;
965     }
966
967     /*
968      * Evaluate the t values in the first num slots of the vals[] array
969      * and place the evaluated values back into the same array. Only
970      * evaluate t values that are within the range <0, 1>, including
971      * the 0 and 1 ends of the range iff the include0 or include1
972      * booleans are true. If an "inflection" equation is handed in,
973      * then any points which represent a point of inflection for that
974      * quadratic equation are also ignored.
975      */

976     private static int evalQuadratic(double vals[], int num,
977                      boolean include0,
978                      boolean include1,
979                      double inflect[],
980                      double c1, double ctrl, double c2) {
981     int j = 0;
982     for (int i = 0; i < num; i++) {
983         double t = vals[i];
984         if ((include0 ? t >= 0 : t > 0) &&
985         (include1 ? t <= 1 : t < 1) &&
986         (inflect == null ||
987          inflect[1] + 2*inflect[2]*t != 0))
988         {
989         double u = 1 - t;
990         vals[j++] = c1*u*u + 2*ctrl*t*u + c2*t*t;
991         }
992     }
993     return j;
994     }
995
996     private static final int BELOW = -2;
997     private static final int LOWEDGE = -1;
998     private static final int INSIDE = 0;
999     private static final int HIGHEDGE = 1;
1000    private static final int ABOVE = 2;
1001
1002    /*
1003     * Determine where coord lies with respect to the range from
1004     * low to high. It is assumed that low <= high. The return
1005     * value is one of the 5 values BELOW, LOWEDGE, INSIDE, HIGHEDGE,
1006     * or ABOVE.
1007     */

1008    private static int getTag(double coord, double low, double high) {
1009    if (coord <= low) {
1010        return (coord < low ? BELOW : LOWEDGE);
1011    }
1012    if (coord >= high) {
1013        return (coord > high ? ABOVE : HIGHEDGE);
1014    }
1015    return INSIDE;
1016    }
1017
1018    /*
1019     * Determine if the pttag represents a coordinate that is already
1020     * in its test range, or is on the border with either of the two
1021     * opttags representing another coordinate that is "towards the
1022     * inside" of that test range. In other words, are either of the
1023     * two "opt" points "drawing the pt inward"?
1024     */

1025    private static boolean inwards(int pttag, int opt1tag, int opt2tag) {
1026    switch (pttag) {
1027    case BELOW:
1028    case ABOVE:
1029    default:
1030        return false;
1031    case LOWEDGE:
1032        return (opt1tag >= INSIDE || opt2tag >= INSIDE);
1033    case INSIDE:
1034        return true;
1035    case HIGHEDGE:
1036        return (opt1tag <= INSIDE || opt2tag <= INSIDE);
1037    }
1038    }
1039
1040    /**
1041     * Tests if the shape of this <code>QuadCurve2D</code> intersects the
1042     * interior of a specified set of rectangular coordinates.
1043     * @param x,&nbsp;y the coordinates of the upper-left corner of the
1044     * specified rectangular area
1045     * @param w the width of the specified rectangular area
1046     * @param h the height of the specified rectangular area
1047     * @return <code>true</code> if the shape of this
1048     * <code>QuadCurve2D</code> intersects the interior of the
1049     * specified set of rectangular coordinates;
1050     * <code>false</code> otherwise.
1051     */

1052    public boolean intersects(double x, double y, double w, double h) {
1053    // Trivially reject non-existant rectangles
1054
if (w < 0 || h < 0) {
1055        return false;
1056    }
1057
1058    // Trivially accept if either endpoint is inside the rectangle
1059
// (not on its border since it may end there and not go inside)
1060
// Record where they lie with respect to the rectangle.
1061
// -1 => left, 0 => inside, 1 => right
1062
double x1 = getX1();
1063    double y1 = getY1();
1064    int x1tag = getTag(x1, x, x+w);
1065    int y1tag = getTag(y1, y, y+h);
1066    if (x1tag == INSIDE && y1tag == INSIDE) {
1067        return true;
1068    }
1069    double x2 = getX2();
1070    double y2 = getY2();
1071    int x2tag = getTag(x2, x, x+w);
1072    int y2tag = getTag(y2, y, y+h);
1073    if (x2tag == INSIDE && y2tag == INSIDE) {
1074        return true;
1075    }
1076    double ctrlx = getCtrlX();
1077    double ctrly = getCtrlY();
1078    int ctrlxtag = getTag(ctrlx, x, x+w);
1079    int ctrlytag = getTag(ctrly, y, y+h);
1080
1081    // Trivially reject if all points are entirely to one side of
1082
// the rectangle.
1083
if (x1tag < INSIDE && x2tag < INSIDE && ctrlxtag < INSIDE) {
1084        return false; // All points left
1085
}
1086    if (y1tag < INSIDE && y2tag < INSIDE && ctrlytag < INSIDE) {
1087        return false; // All points above
1088
}
1089    if (x1tag > INSIDE && x2tag > INSIDE && ctrlxtag > INSIDE) {
1090        return false; // All points right
1091
}
1092    if (y1tag > INSIDE && y2tag > INSIDE && ctrlytag > INSIDE) {
1093        return false; // All points below
1094
}
1095
1096    // Test for endpoints on the edge where either the segment
1097
// or the curve is headed "inwards" from them
1098
// Note: These tests are a superset of the fast endpoint tests
1099
// above and thus repeat those tests, but take more time
1100
// and cover more cases
1101
if (inwards(x1tag, x2tag, ctrlxtag) &&
1102        inwards(y1tag, y2tag, ctrlytag))
1103    {
1104        // First endpoint on border with either edge moving inside
1105
return true;
1106    }
1107    if (inwards(x2tag, x1tag, ctrlxtag) &&
1108        inwards(y2tag, y1tag, ctrlytag))
1109    {
1110        // Second endpoint on border with either edge moving inside
1111
return true;
1112    }
1113
1114    // Trivially accept if endpoints span directly across the rectangle
1115
boolean xoverlap = (x1tag * x2tag <= 0);
1116    boolean yoverlap = (y1tag * y2tag <= 0);
1117    if (x1tag == INSIDE && x2tag == INSIDE && yoverlap) {
1118        return true;
1119    }
1120    if (y1tag == INSIDE && y2tag == INSIDE && xoverlap) {
1121        return true;
1122    }
1123
1124    // We now know that both endpoints are outside the rectangle
1125
// but the 3 points are not all on one side of the rectangle.
1126
// Therefore the curve cannot be contained inside the rectangle,
1127
// but the rectangle might be contained inside the curve, or
1128
// the curve might intersect the boundary of the rectangle.
1129

1130    double[] eqn = new double[3];
1131    double[] res = new double[3];
1132    if (!yoverlap) {
1133        // Both y coordinates for the closing segment are above or
1134
// below the rectangle which means that we can only intersect
1135
// if the curve crosses the top (or bottom) of the rectangle
1136
// in more than one place and if those crossing locations
1137
// span the horizontal range of the rectangle.
1138
fillEqn(eqn, (y1tag < INSIDE ? y : y+h), y1, ctrly, y2);
1139        return (solveQuadratic(eqn, res) == 2 &&
1140            evalQuadratic(res, 2, true, true, null,
1141                  x1, ctrlx, x2) == 2 &&
1142            getTag(res[0], x, x+w) * getTag(res[1], x, x+w) <= 0);
1143    }
1144
1145    // Y ranges overlap. Now we examine the X ranges
1146
if (!xoverlap) {
1147        // Both x coordinates for the closing segment are left of
1148
// or right of the rectangle which means that we can only
1149
// intersect if the curve crosses the left (or right) edge
1150
// of the rectangle in more than one place and if those
1151
// crossing locations span the vertical range of the rectangle.
1152
fillEqn(eqn, (x1tag < INSIDE ? x : x+w), x1, ctrlx, x2);
1153        return (solveQuadratic(eqn, res) == 2 &&
1154            evalQuadratic(res, 2, true, true, null,
1155                  y1, ctrly, y2) == 2 &&
1156            getTag(res[0], y, y+h) * getTag(res[1], y, y+h) <= 0);
1157    }
1158
1159    // The X and Y ranges of the endpoints overlap the X and Y
1160
// ranges of the rectangle, now find out how the endpoint
1161
// line segment intersects the Y range of the rectangle
1162
double dx = x2 - x1;
1163    double dy = y2 - y1;
1164    double k = y2 * x1 - x2 * y1;
1165    int c1tag, c2tag;
1166    if (y1tag == INSIDE) {
1167        c1tag = x1tag;
1168    } else {
1169        c1tag = getTag((k + dx * (y1tag < INSIDE ? y : y+h)) / dy, x, x+w);
1170    }
1171    if (y2tag == INSIDE) {
1172        c2tag = x2tag;
1173    } else {
1174        c2tag = getTag((k + dx * (y2tag < INSIDE ? y : y+h)) / dy, x, x+w);
1175    }
1176    // If the part of the line segment that intersects the Y range
1177
// of the rectangle crosses it horizontally - trivially accept
1178
if (c1tag * c2tag <= 0) {
1179        return true;
1180    }
1181
1182    // Now we know that both the X and Y ranges intersect and that
1183
// the endpoint line segment does not directly cross the rectangle.
1184
//
1185
// We can almost treat this case like one of the cases above
1186
// where both endpoints are to one side, except that we will
1187
// only get one intersection of the curve with the vertical
1188
// side of the rectangle. This is because the endpoint segment
1189
// accounts for the other intersection.
1190
//
1191
// (Remember there is overlap in both the X and Y ranges which
1192
// means that the segment must cross at least one vertical edge
1193
// of the rectangle - in particular, the "near vertical side" -
1194
// leaving only one intersection for the curve.)
1195
//
1196
// Now we calculate the y tags of the two intersections on the
1197
// "near vertical side" of the rectangle. We will have one with
1198
// the endpoint segment, and one with the curve. If those two
1199
// vertical intersections overlap the Y range of the rectangle,
1200
// we have an intersection. Otherwise, we don't.
1201

1202    // c1tag = vertical intersection class of the endpoint segment
1203
//
1204
// Choose the y tag of the endpoint that was not on the same
1205
// side of the rectangle as the subsegment calculated above.
1206
// Note that we can "steal" the existing Y tag of that endpoint
1207
// since it will be provably the same as the vertical intersection.
1208
c1tag = ((c1tag * x1tag <= 0) ? y1tag : y2tag);
1209
1210    // c2tag = vertical intersection class of the curve
1211
//
1212
// We have to calculate this one the straightforward way.
1213
// Note that the c2tag can still tell us which vertical edge
1214
// to test against.
1215
fillEqn(eqn, (c2tag < INSIDE ? x : x+w), x1, ctrlx, x2);
1216    int num = solveQuadratic(eqn, res);
1217
1218    // Note: We should be able to assert(num == 2); since the
1219
// X range "crosses" (not touches) the vertical boundary,
1220
// but we pass num to evalQuadratic for completeness.
1221
evalQuadratic(res, num, true, true, null, y1, ctrly, y2);
1222
1223    // Note: We can assert(num evals == 1); since one of the
1224
// 2 crossings will be out of the [0,1] range.
1225
c2tag = getTag(res[0], y, y+h);
1226
1227    // Finally, we have an intersection if the two crossings
1228
// overlap the Y range of the rectangle.
1229
return (c1tag * c2tag <= 0);
1230    }
1231
1232    /**
1233     * Tests if the shape of this <code>QuadCurve2D</code> intersects the
1234     * interior of a specified <code>Rectangle2D</code>.
1235     * @param r the specified <code>Rectangle2D</code>
1236     * @return <code>true</code> if the shape of this
1237     * <code>QuadCurve2D</code> intersects the interior of
1238     * the specified <code>Rectangle2D</code>;
1239     * <code>false</code> otherwise.
1240     */

1241    public boolean intersects(Rectangle2D JavaDoc r) {
1242    return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1243    }
1244
1245    /**
1246     * Tests if the interior of the shape of this
1247     * <code>QuadCurve2D</code> entirely contains the specified
1248     * set of rectangular coordinates.
1249     * @param x,&nbsp;y the coordinates of the upper-left corner of the
1250     * specified rectangular area
1251     * @param w the width of the specified rectangular area
1252     * @param h the height of the specified rectangular area
1253     * @return <code>true</code> if the interior of the shape of this
1254     * <code>QuadCurve2D</code> entirely contains the specified
1255     * rectangluar area; <code>false</code> otherwise.
1256     */

1257    public boolean contains(double x, double y, double w, double h) {
1258    // Assertion: Quadratic curves closed by connecting their
1259
// endpoints are always convex.
1260
return (contains(x, y) &&
1261        contains(x + w, y) &&
1262        contains(x + w, y + h) &&
1263        contains(x, y + h));
1264    }
1265
1266    /**
1267     * Tests if the interior of the shape of this
1268     * <code>QuadCurve2D</code> entirely contains the specified
1269     * <code>Rectangle2D</code>.
1270     * @param r the specified <code>Rectangle2D</code>
1271     * @return <code>true</code> if the interior of the shape of this
1272     * <code>QuadCurve2D</code> entirely contains the specified
1273     * <code>Rectangle2D</code>; <code>false</code> otherwise.
1274     */

1275    public boolean contains(Rectangle2D JavaDoc r) {
1276    return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1277    }
1278
1279    /**
1280     * Returns the bounding box of this <code>QuadCurve2D</code>.
1281     * @return a {@link Rectangle} that is the bounding box of the shape
1282     * of this <code>QuadCurve2D</code>.
1283     */

1284    public Rectangle JavaDoc getBounds() {
1285    return getBounds2D().getBounds();
1286    }
1287
1288    /**
1289     * Returns an iteration object that defines the boundary of the
1290     * shape of this <code>QuadCurve2D</code>.
1291     * The iterator for this class is not multi-threaded safe,
1292     * which means that this <code>QuadCurve2D</code> class does not
1293     * guarantee that modifications to the geometry of this
1294     * <code>QuadCurve2D</code> object do not affect any iterations of
1295     * that geometry that are already in process.
1296     * @param at an optional {@link AffineTransform} to apply to the
1297     * shape boundary
1298     * @return a {@link PathIterator} object that defines the boundary
1299     * of the shape.
1300     */

1301    public PathIterator JavaDoc getPathIterator(AffineTransform JavaDoc at) {
1302    return new QuadIterator JavaDoc(this, at);
1303    }
1304
1305    /**
1306     * Returns an iteration object that defines the boundary of the
1307     * flattened shape of this <code>QuadCurve2D</code>.
1308     * The iterator for this class is not multi-threaded safe,
1309     * which means that this <code>QuadCurve2D</code> class does not
1310     * guarantee that modifications to the geometry of this
1311     * <code>QuadCurve2D</code> object do not affect any iterations of
1312     * that geometry that are already in process.
1313     * @param at an optional <code>AffineTransform</code> to apply
1314     * to the boundary of the shape
1315     * @param flatness the maximum distance that the control points for a
1316     * subdivided curve can be with respect to a line connecting
1317     * the endpoints of this curve before this curve is
1318     * replaced by a straight line connecting the endpoints.
1319     * @return a <code>PathIterator</code> object that defines the
1320     * flattened boundary of the shape.
1321     */

1322    public PathIterator JavaDoc getPathIterator(AffineTransform JavaDoc at, double flatness) {
1323    return new FlatteningPathIterator JavaDoc(getPathIterator(at), flatness);
1324    }
1325
1326    /**
1327     * Creates a new object of the same class and with the same contents
1328     * as this object.
1329     *
1330     * @return a clone of this instance.
1331     * @exception OutOfMemoryError if there is not enough memory.
1332     * @see java.lang.Cloneable
1333     * @since 1.2
1334     */

1335    public Object JavaDoc clone() {
1336    try {
1337        return super.clone();
1338    } catch (CloneNotSupportedException JavaDoc e) {
1339        // this shouldn't happen, since we are Cloneable
1340
throw new InternalError JavaDoc();
1341    }
1342    }
1343}
1344
Popular Tags