KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > geom > ExtendedGeneralPath


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.geom;
19
20 import java.awt.Shape JavaDoc;
21 import java.awt.geom.AffineTransform JavaDoc;
22 import java.awt.geom.Arc2D JavaDoc;
23 import java.awt.geom.GeneralPath JavaDoc;
24 import java.awt.geom.PathIterator JavaDoc;
25 import java.awt.geom.Point2D JavaDoc;
26 import java.awt.geom.Rectangle2D JavaDoc;
27
28 /**
29  * The <code>ExtendedGeneralPath</code> class represents a geometric
30  * path constructed from straight lines, quadratic and cubic (Bezier)
31  * curves and elliptical arc. This class delegates lines and curves to
32  * an enclosed <code>GeneralPath</code>. Elliptical arc is implemented
33  * using an <code>Arc2D</code> in float precision.
34  *
35  * <p><b>Warning</b> : An elliptical arc may be composed of several
36  * path segments. For futher details, see the SVG Appendix&nbsp;F.6
37  *
38  * @author <a HREF="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
39  * @version $Id: ExtendedGeneralPath.java,v 1.9 2005/03/27 08:58:32 cam Exp $
40  */

41 public class ExtendedGeneralPath implements ExtendedShape, Cloneable JavaDoc {
42
43     /** The enclosed general path. */
44     protected GeneralPath JavaDoc path;
45
46     int numVals = 0;
47     int numSeg = 0;
48     float [] values = null;
49     int [] types = null;
50
51     float mx, my, cx, cy;
52
53    /**
54      * Constructs a new <code>ExtendedGeneralPath</code>.
55      */

56     public ExtendedGeneralPath() {
57         path = new GeneralPath JavaDoc();
58     }
59
60     /**
61      * Constructs a new <code>ExtendedGeneralPath</code> with the
62      * specified winding rule to control operations that require the
63      * interior of the path to be defined.
64      */

65     public ExtendedGeneralPath(int rule) {
66         path = new GeneralPath JavaDoc(rule);
67     }
68
69     /**
70      * Constructs a new <code>ExtendedGeneralPath</code> object with
71      * the specified winding rule and the specified initial capacity
72      * to store path coordinates.
73      */

74     public ExtendedGeneralPath(int rule, int initialCapacity) {
75         path = new GeneralPath JavaDoc(rule, initialCapacity);
76     }
77
78     /**
79      * Constructs a new <code>ExtendedGeneralPath</code> object from
80      * an arbitrary <code>Shape</code> object.
81      */

82     public ExtendedGeneralPath(Shape JavaDoc s) {
83         this();
84         append(s, false);
85     }
86
87     /**
88      * Adds an elliptical arc, defined by two radii, an angle from the
89      * x-axis, a flag to choose the large arc or not, a flag to
90      * indicate if we increase or decrease the angles and the final
91      * point of the arc.
92      *
93      * @param rx the x radius of the ellipse
94      * @param ry the y radius of the ellipse
95      *
96      * @param angle the angle from the x-axis of the current
97      * coordinate system to the x-axis of the ellipse in degrees.
98      *
99      * @param largeArcFlag the large arc flag. If true the arc
100      * spanning less than or equal to 180 degrees is chosen, otherwise
101      * the arc spanning greater than 180 degrees is chosen
102      *
103      * @param sweepFlag the sweep flag. If true the line joining
104      * center to arc sweeps through decreasing angles otherwise it
105      * sweeps through increasing angles
106      *
107      * @param x the absolute x coordinate of the final point of the arc.
108      * @param y the absolute y coordinate of the final point of the arc.
109      */

110     public synchronized void arcTo(float rx, float ry,
111                                    float angle,
112                                    boolean largeArcFlag,
113                                    boolean sweepFlag,
114                                    float x, float y) {
115
116         // Ensure radii are valid
117
if (rx == 0 || ry == 0) {
118             lineTo((float) x, (float) y);
119             return;
120         }
121
122         checkMoveTo(); // check if prev command was moveto
123

124         // Get the current (x, y) coordinates of the path
125
double x0 = cx;
126         double y0 = cy;
127         if (x0 == x && y0 == y) {
128             // If the endpoints (x, y) and (x0, y0) are identical, then this
129
// is equivalent to omitting the elliptical arc segment entirely.
130
return;
131         }
132
133         Arc2D JavaDoc arc = computeArc(x0, y0, rx, ry, angle,
134                                largeArcFlag, sweepFlag, x, y);
135         if (arc == null) return;
136
137         AffineTransform JavaDoc t = AffineTransform.getRotateInstance
138             (Math.toRadians(angle), arc.getCenterX(), arc.getCenterY());
139         Shape JavaDoc s = t.createTransformedShape(arc);
140         path.append(s, true);
141
142         makeRoom(7);
143         types [numSeg++] = ExtendedPathIterator.SEG_ARCTO;
144         values[numVals++] = rx;
145         values[numVals++] = ry;
146         values[numVals++] = angle;
147         values[numVals++] = largeArcFlag?1:0;
148         values[numVals++] = sweepFlag?1:0;
149         cx = values[numVals++] = x;
150         cy = values[numVals++] = y;
151     }
152
153
154     /**
155      * This constructs an unrotated Arc2D from the SVG specification of an
156      * Elliptical arc. To get the final arc you need to apply a rotation
157      * transform such as:
158      *
159      * AffineTransform.getRotateInstance
160      * (angle, arc.getX()+arc.getWidth()/2, arc.getY()+arc.getHeight()/2);
161      */

162     public static Arc2D JavaDoc computeArc(double x0, double y0,
163                                    double rx, double ry,
164                                    double angle,
165                                    boolean largeArcFlag,
166                                    boolean sweepFlag,
167                                    double x, double y) {
168         //
169
// Elliptical arc implementation based on the SVG specification notes
170
//
171

172         // Compute the half distance between the current and the final point
173
double dx2 = (x0 - x) / 2.0;
174         double dy2 = (y0 - y) / 2.0;
175         // Convert angle from degrees to radians
176
angle = Math.toRadians(angle % 360.0);
177         double cosAngle = Math.cos(angle);
178         double sinAngle = Math.sin(angle);
179
180         //
181
// Step 1 : Compute (x1, y1)
182
//
183
double x1 = (cosAngle * dx2 + sinAngle * dy2);
184         double y1 = (-sinAngle * dx2 + cosAngle * dy2);
185         // Ensure radii are large enough
186
rx = Math.abs(rx);
187         ry = Math.abs(ry);
188         double Prx = rx * rx;
189         double Pry = ry * ry;
190         double Px1 = x1 * x1;
191         double Py1 = y1 * y1;
192         // check that radii are large enough
193
double radiiCheck = Px1/Prx + Py1/Pry;
194         if (radiiCheck > 1) {
195             rx = Math.sqrt(radiiCheck) * rx;
196             ry = Math.sqrt(radiiCheck) * ry;
197             Prx = rx * rx;
198             Pry = ry * ry;
199         }
200
201         //
202
// Step 2 : Compute (cx1, cy1)
203
//
204
double sign = (largeArcFlag == sweepFlag) ? -1 : 1;
205         double sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1));
206         sq = (sq < 0) ? 0 : sq;
207         double coef = (sign * Math.sqrt(sq));
208         double cx1 = coef * ((rx * y1) / ry);
209         double cy1 = coef * -((ry * x1) / rx);
210
211         //
212
// Step 3 : Compute (cx, cy) from (cx1, cy1)
213
//
214
double sx2 = (x0 + x) / 2.0;
215         double sy2 = (y0 + y) / 2.0;
216         double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1);
217         double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1);
218
219         //
220
// Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
221
//
222
double ux = (x1 - cx1) / rx;
223         double uy = (y1 - cy1) / ry;
224         double vx = (-x1 - cx1) / rx;
225         double vy = (-y1 - cy1) / ry;
226         double p, n;
227         // Compute the angle start
228
n = Math.sqrt((ux * ux) + (uy * uy));
229         p = ux; // (1 * ux) + (0 * uy)
230
sign = (uy < 0) ? -1d : 1d;
231         double angleStart = Math.toDegrees(sign * Math.acos(p / n));
232
233         // Compute the angle extent
234
n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
235         p = ux * vx + uy * vy;
236         sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
237         double angleExtent = Math.toDegrees(sign * Math.acos(p / n));
238         if(!sweepFlag && angleExtent > 0) {
239             angleExtent -= 360f;
240         } else if (sweepFlag && angleExtent < 0) {
241             angleExtent += 360f;
242         }
243         angleExtent %= 360f;
244         angleStart %= 360f;
245
246         //
247
// We can now build the resulting Arc2D in double precision
248
//
249
Arc2D.Double JavaDoc arc = new Arc2D.Double JavaDoc();
250         arc.x = cx - rx;
251         arc.y = cy - ry;
252         arc.width = rx * 2.0;
253         arc.height = ry * 2.0;
254         arc.start = -angleStart;
255         arc.extent = -angleExtent;
256
257         return arc;
258     }
259
260     /**
261      * Delegates to the enclosed <code>GeneralPath</code>.
262      */

263     public synchronized void moveTo(float x, float y) {
264         // Don't add moveto to general path unless there is a reason.
265
makeRoom(2);
266         types [numSeg++] = PathIterator.SEG_MOVETO;
267         cx = mx = values[numVals++] = x;
268         cy = my = values[numVals++] = y;
269         
270     }
271
272     /**
273      * Delegates to the enclosed <code>GeneralPath</code>.
274      */

275     public synchronized void lineTo(float x, float y) {
276         checkMoveTo(); // check if prev command was moveto
277
path.lineTo(x, y);
278
279         makeRoom(2);
280         types [numSeg++] = PathIterator.SEG_LINETO;
281         cx = values[numVals++] = x;
282         cy = values[numVals++] = y;
283     }
284
285     /**
286      * Delegates to the enclosed <code>GeneralPath</code>.
287      */

288     public synchronized void quadTo(float x1, float y1, float x2, float y2) {
289         checkMoveTo(); // check if prev command was moveto
290
path.quadTo(x1, y1, x2, y2);
291
292         makeRoom(4);
293         types [numSeg++] = PathIterator.SEG_QUADTO;
294         values[numVals++] = x1;
295         values[numVals++] = y1;
296         cx = values[numVals++] = x2;
297         cy = values[numVals++] = y2;
298     }
299
300     /**
301      * Delegates to the enclosed <code>GeneralPath</code>.
302      */

303     public synchronized void curveTo(float x1, float y1,
304                                      float x2, float y2,
305                                      float x3, float y3) {
306         checkMoveTo(); // check if prev command was moveto
307
path.curveTo(x1, y1, x2, y2, x3, y3);
308
309         makeRoom(6);
310         types [numSeg++] = PathIterator.SEG_CUBICTO;
311         values[numVals++] = x1;
312         values[numVals++] = y1;
313         values[numVals++] = x2;
314         values[numVals++] = y2;
315         cx = values[numVals++] = x3;
316         cy = values[numVals++] = y3;
317     }
318
319     /**
320      * Delegates to the enclosed <code>GeneralPath</code>.
321      */

322     public synchronized void closePath() {
323         // Don't double close path.
324
if ((numSeg != 0) && (types[numSeg-1] == PathIterator.SEG_CLOSE))
325             return;
326
327         // Only close path if the previous command wasn't a moveto
328
if ((numSeg != 0) && (types[numSeg-1] != PathIterator.SEG_MOVETO))
329             path.closePath();
330
331         makeRoom(0);
332         types [numSeg++] = PathIterator.SEG_CLOSE;
333         cx = mx;
334         cy = my;
335     }
336
337     /**
338      * Checks if previous command was a moveto command,
339      * skipping a close command (if present).
340      */

341     protected void checkMoveTo() {
342         if (numSeg == 0) return;
343
344         switch(types[numSeg-1]) {
345
346         case PathIterator.SEG_MOVETO:
347             path.moveTo(values[numVals-2], values[numVals-1]);
348             break;
349
350         case PathIterator.SEG_CLOSE:
351             if (numSeg == 1) return;
352             if (types[numSeg-2] == PathIterator.SEG_MOVETO)
353                 path.moveTo(values[numVals-2], values[numVals-1]);
354             break;
355
356         default:
357             break;
358         }
359     }
360
361     /**
362      * Delegates to the enclosed <code>GeneralPath</code>.
363      */

364     public void append(Shape JavaDoc s, boolean connect) {
365         append(s.getPathIterator(new AffineTransform JavaDoc()), connect);
366     }
367
368     /**
369      * Delegates to the enclosed <code>GeneralPath</code>.
370      */

371     public void append(PathIterator JavaDoc pi, boolean connect) {
372         
373         while (!pi.isDone()) {
374             double [] vals = new double[6];
375             int type = pi.currentSegment(vals);
376             pi.next();
377             if (connect && (numVals != 0)) {
378                 if (type == PathIterator.SEG_MOVETO) {
379                     double x = vals[0];
380                     double y = vals[1];
381                     if ((x != cx) ||
382                         (y != cy)) {
383                         // Change MOVETO to LINETO.
384
type = PathIterator.SEG_LINETO;
385                     } else {
386                         // Redundent segment (move to current loc) drop it...
387
if (pi.isDone()) break; // Nothing interesting
388
type = pi.currentSegment(vals);
389                         pi.next();
390                     }
391                 }
392                 connect = false;
393             }
394
395             switch(type) {
396             case PathIterator.SEG_CLOSE: closePath(); break;
397             case PathIterator.SEG_MOVETO:
398                 moveTo ((float)vals[0], (float)vals[1]); break;
399             case PathIterator.SEG_LINETO:
400                 lineTo ((float)vals[0], (float)vals[1]); break;
401             case PathIterator.SEG_QUADTO:
402                 quadTo ((float)vals[0], (float)vals[1],
403                         (float)vals[2], (float)vals[3]); break;
404             case PathIterator.SEG_CUBICTO:
405                 curveTo((float)vals[0], (float)vals[1],
406                         (float)vals[2], (float)vals[3],
407                         (float)vals[4], (float)vals[5]); break;
408             }
409         }
410     }
411
412     /**
413      * Delegates to the enclosed <code>GeneralPath</code>.
414      */

415     public void append(ExtendedPathIterator epi, boolean connect) {
416         while (!epi.isDone()) {
417             float [] vals = new float[7];
418             int type = epi.currentSegment(vals);
419             epi.next();
420             if (connect && (numVals != 0)) {
421                 if (type == PathIterator.SEG_MOVETO) {
422                     float x = vals[0];
423                     float y = vals[1];
424                     if ((x != cx) ||
425                         (y != cy)) {
426                         // Change MOVETO to LINETO.
427
type = PathIterator.SEG_LINETO;
428                     } else {
429                         // Redundent segment (move to current loc) drop it...
430
if (epi.isDone()) break; // Nothing interesting
431
type = epi.currentSegment(vals);
432                         epi.next();
433                     }
434                 }
435                 connect = false;
436             }
437
438             switch(type) {
439             case PathIterator.SEG_CLOSE: closePath(); break;
440             case PathIterator.SEG_MOVETO:
441                 moveTo ((float)vals[0], (float)vals[1]); break;
442             case PathIterator.SEG_LINETO:
443                 lineTo ((float)vals[0], (float)vals[1]); break;
444             case PathIterator.SEG_QUADTO:
445                 quadTo ((float)vals[0], (float)vals[1],
446                         (float)vals[2], (float)vals[3]); break;
447             case PathIterator.SEG_CUBICTO:
448                 curveTo((float)vals[0], (float)vals[1],
449                         (float)vals[2], (float)vals[3],
450                         (float)vals[4], (float)vals[5]); break;
451             case ExtendedPathIterator.SEG_ARCTO:
452                 arcTo (vals[0], vals[1], vals[2],
453                         (vals[3]!=0), (vals[4]!=0),
454                         vals[5], vals[6]); break;
455             }
456         }
457     }
458
459     /**
460      * Delegates to the enclosed <code>GeneralPath</code>.
461      */

462     public synchronized int getWindingRule() {
463         return path.getWindingRule();
464     }
465
466     /**
467      * Delegates to the enclosed <code>GeneralPath</code>.
468      */

469     public void setWindingRule(int rule) {
470         path.setWindingRule(rule);
471     }
472
473     /**
474      * Delegates to the enclosed <code>GeneralPath</code>.
475      */

476     public synchronized Point2D JavaDoc getCurrentPoint() {
477         if (numVals == 0) return null;
478         return new Point2D.Double JavaDoc(cx, cy);
479     }
480
481     /**
482      * Delegates to the enclosed <code>GeneralPath</code>.
483      */

484     public synchronized void reset() {
485         path.reset();
486
487         numSeg = 0;
488         numVals = 0;
489     }
490
491     /**
492      * Delegates to the enclosed <code>GeneralPath</code>.
493      */

494     public void transform(AffineTransform JavaDoc at) {
495         if (at.getType() != AffineTransform.TYPE_IDENTITY)
496             throw new IllegalArgumentException JavaDoc
497                 ("ExtendedGeneralPaths can not be transformed");
498     }
499
500     /**
501      * Delegates to the enclosed <code>GeneralPath</code>.
502      */

503     public synchronized Shape JavaDoc createTransformedShape(AffineTransform JavaDoc at) {
504         return path.createTransformedShape(at);
505     }
506
507     /**
508      * Delegates to the enclosed <code>GeneralPath</code>.
509      */

510     public java.awt.Rectangle JavaDoc getBounds() {
511         return path.getBounds();
512     }
513
514     /**
515      * Delegates to the enclosed <code>GeneralPath</code>.
516      */

517     public synchronized Rectangle2D JavaDoc getBounds2D() {
518         return path.getBounds2D();
519     }
520
521     /**
522      * Delegates to the enclosed <code>GeneralPath</code>.
523      */

524     public boolean contains(double x, double y) {
525         return path.contains(x, y);
526     }
527
528     /**
529      * Delegates to the enclosed <code>GeneralPath</code>.
530      */

531     public boolean contains(Point2D JavaDoc p) {
532         return path.contains(p);
533     }
534
535     /**
536      * Delegates to the enclosed <code>GeneralPath</code>.
537      */

538     public boolean contains(double x, double y, double w, double h) {
539         return path.contains(x, y, w, h);
540     }
541
542     /**
543      * Delegates to the enclosed <code>GeneralPath</code>.
544      */

545     public boolean contains(Rectangle2D JavaDoc r) {
546         return path.contains(r);
547     }
548
549     /**
550      * Delegates to the enclosed <code>GeneralPath</code>.
551      */

552     public boolean intersects(double x, double y, double w, double h) {
553         return path.intersects(x, y, w, h);
554     }
555
556     /**
557      * Delegates to the enclosed <code>GeneralPath</code>.
558      */

559     public boolean intersects(Rectangle2D JavaDoc r) {
560         return path.intersects(r);
561     }
562
563     /**
564      * Delegates to the enclosed <code>GeneralPath</code>.
565      */

566     public PathIterator JavaDoc getPathIterator(AffineTransform JavaDoc at) {
567         return path.getPathIterator(at);
568     }
569
570     /**
571      * Delegates to the enclosed <code>GeneralPath</code>.
572      */

573     public PathIterator JavaDoc getPathIterator(AffineTransform JavaDoc at, double flatness) {
574         return path.getPathIterator(at, flatness);
575     }
576
577     /**
578      * Delegates to the enclosed <code>GeneralPath</code>.
579      */

580     public ExtendedPathIterator getExtendedPathIterator() {
581         return new EPI();
582     }
583
584     class EPI implements ExtendedPathIterator {
585         int segNum = 0;
586         int valsIdx = 0;
587
588         public int currentSegment(double[] coords) {
589             int ret = types[segNum];
590             switch (ret) {
591             case SEG_CLOSE: break;
592             case SEG_MOVETO:
593             case SEG_LINETO:
594                 coords[0] = values[valsIdx];
595                 coords[1] = values[valsIdx+1];
596                 break;
597             case SEG_QUADTO:
598                 coords[0] = values[valsIdx];
599                 coords[1] = values[valsIdx+1];
600                 coords[2] = values[valsIdx+2];
601                 coords[3] = values[valsIdx+3];
602                 break;
603             case SEG_CUBICTO:
604                 coords[0] = values[valsIdx];
605                 coords[1] = values[valsIdx+1];
606                 coords[2] = values[valsIdx+2];
607                 coords[3] = values[valsIdx+3];
608                 coords[4] = values[valsIdx+4];
609                 coords[5] = values[valsIdx+5];
610                 break;
611             case SEG_ARCTO:
612                 coords[0] = values[valsIdx];
613                 coords[1] = values[valsIdx+1];
614                 coords[2] = values[valsIdx+2];
615                 coords[3] = values[valsIdx+3];
616                 coords[4] = values[valsIdx+4];
617                 coords[5] = values[valsIdx+5];
618                 coords[6] = values[valsIdx+6];
619                 break;
620             }
621             // System.out.println("Seg: [" + segNum + "] type: " + ret +
622
// " vals: [" + coords[0] + ", " + coords[1] +
623
// "]");
624
return ret;
625         }
626
627         public int currentSegment(float[] coords) {
628             int ret = types[segNum];
629             switch (ret) {
630             case SEG_CLOSE: break;
631             case SEG_MOVETO:
632             case SEG_LINETO:
633                 coords[0] = (float)values[valsIdx];
634                 coords[1] = (float)values[valsIdx+1];
635                 break;
636             case SEG_QUADTO:
637                 coords[0] = (float)values[valsIdx];
638                 coords[1] = (float)values[valsIdx+1];
639                 coords[2] = (float)values[valsIdx+2];
640                 coords[3] = (float)values[valsIdx+3];
641                 break;
642             case SEG_CUBICTO:
643                 coords[0] = (float)values[valsIdx];
644                 coords[1] = (float)values[valsIdx+1];
645                 coords[2] = (float)values[valsIdx+2];
646                 coords[3] = (float)values[valsIdx+3];
647                 coords[4] = (float)values[valsIdx+4];
648                 coords[5] = (float)values[valsIdx+5];
649                 break;
650             case SEG_ARCTO:
651                 coords[0] = (float)values[valsIdx];
652                 coords[1] = (float)values[valsIdx+1];
653                 coords[2] = (float)values[valsIdx+2];
654                 coords[3] = (float)values[valsIdx+3];
655                 coords[4] = (float)values[valsIdx+4];
656                 coords[5] = (float)values[valsIdx+5];
657                 coords[6] = (float)values[valsIdx+6];
658                 break;
659             }
660             return ret;
661         }
662
663         public int getWindingRule() {
664             return path.getWindingRule();
665         }
666         public boolean isDone() {
667             return segNum == numSeg;
668         }
669         public void next() {
670             int type = types[segNum++];
671             switch (type) {
672             case SEG_CLOSE: break;
673             case SEG_MOVETO:
674             case SEG_LINETO: valsIdx+=2; break;
675             case SEG_QUADTO: valsIdx+=4; break;
676             case SEG_CUBICTO:valsIdx+=6; break;
677             case SEG_ARCTO: valsIdx+=7; break;
678             }
679         }
680     }
681
682     /**
683      * Delegates to the enclosed <code>GeneralPath</code>.
684      */

685     public Object JavaDoc clone() {
686         try {
687             ExtendedGeneralPath result = (ExtendedGeneralPath) super.clone();
688             result.path = (GeneralPath JavaDoc) path.clone();
689
690             result.values = new float[values.length];
691             System.arraycopy(result.values, 0, values, 0, values.length);
692             result.numVals = numVals;
693
694             result.types = new int[types.length];
695             System.arraycopy(result.types, 0, types, 0, types.length);
696             result.numSeg = numSeg;
697
698             return result;
699         } catch (CloneNotSupportedException JavaDoc ex) {}
700         return null;
701     }
702
703     private void makeRoom(int numValues) {
704         if (values == null) {
705             values = new float[2*numValues];
706             types = new int[2];
707             numVals = 0;
708             numSeg = 0;
709             return;
710         }
711         
712         if ((numVals + numValues) > values.length) {
713             int nlen = values.length*2;
714             if (nlen < (numVals + numValues))
715                 nlen = numVals + numValues;
716         
717             float [] nvals = new float[nlen];
718             System.arraycopy(values, 0, nvals, 0, numVals);
719             values = nvals;
720         }
721
722         if (numSeg == types.length) {
723             int [] ntypes = new int[types.length*2];
724             System.arraycopy(types, 0, ntypes, 0, types.length);
725             types = ntypes;
726         }
727     }
728 }
729
Popular Tags