1    // FIXME
2    // Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
3    package org.xwt;
4    import org.xwt.util.*;
5    import java.util.*;
6    
7    // FIXME: offer a "subpixel" mode where we pass floats to the Platform and don't do any snapping
8    // FIXME: fracture when realizing instead of when parsing?
9    
10   /*
11       v1.0
12       - textpath
13       - gradients
14       - patterns
15       - clipping/masking
16       - filters (filtering of a group must be performed AFTER the group is assembled; sep. canvas)
17   
18       v1.1
19       - bump caps [requires Paint that can fill circles...] [remember to distinguish between closed/unclosed]
20       - line joins
21           - mitre    (hard)
22           - bevel    (easy)
23           - bump     (easy, but requires 'round' Paint)
24       - subtree sharing? otherwise the memory consumption might be outrageous... clone="" attribute?
25       - better clipping
26           - intersect clip regions (linearity)
27           - clip on trapezoids, not pixels
28       - faster gradients and patterns:
29           - transform each corner of the trapezoid and then interpolate
30   */
31   
32   /** XWT's fully conformant Static SVG Viewer; see SVG spec, section G.7 */
33   public final class VectorGraphics {
34   
35       // Private Constants ///////////////////////////////////////////////////////////////////
36   
37       private static final int DEFAULT_PATHLEN = 1000;
38       private static final float PI = (float)Math.PI;
39   
40   
41       // Public entry points /////////////////////////////////////////////////////////////////
42   
43       public static VectorPath parseVectorPath(String s) {
44           if (s == null) return null;
45           PathTokenizer t = new PathTokenizer(s);
46           VectorPath ret = new VectorPath();
47           char last_command = 'M';
48           boolean first = true;
49           while(t.hasMoreTokens()) {
50               char command = t.parseCommand();
51               if (first && command != 'M') throw new RuntimeException("the first command of a path must be 'M'");
52               first = false;
53               boolean relative = Character.toLowerCase(command) == command;
54               command = Character.toLowerCase(command);
55               ret.parseSingleCommandAndArguments(t, command, relative);
56               last_command = command;
57           }
58           return ret;
59       }
60   
61   
62       // Affine //////////////////////////////////////////////////////////////////////////////
63   
64       /** an affine transform; all operations are destructive */
65       public static final class Affine {
66   
67   	//  [ a b e ]
68   	//  [ c d f ]
69   	//  [ 0 0 1 ]
70           public floatfloatfloatfloatfloat	Affine(float _a, float _b, float _c, float _d, float _e, float _f) { a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; }
71   	public String toString() { return "[ " + a + ", " + b + ", " + c + ", " + d + ", " + e + ", " + f + " ]"; }
72   	public Affine copy() { return new Affine(a, b, c, d, e, f); }
73           public static Affine identity() { return new Affine(1, 0, 0, 1, 0, 0); }
74   	public static Affine scale(float sx, float sy) { return new Affine(sx, 0, 0, sy, 0, 0); }
75   	public static Affine shear(float degrees) {
76               return new Affine(1, 0, (float)Math.tan(degrees * (float)(Math.PI / 180.0)), 1, 0, 0); }
77   	public static Affine translate(float tx, float ty) { return new Affine(1, 0, 0, 1, tx, ty); }
78   	public static Affine flip(boolean horiz, boolean vert) { return new Affine(horiz ? -1 : 1, 0, 0, vert ? -1 : 1, 0, 0); }
79           public float multiply_px(float x, float y) { return x * a + y * c + e; }
80   	public float multiply_py(float x, float y) { return x * b + y * d + f; }
81           public boolean equalsIgnoringTranslation(Affine x) { return a == x.a && b == x.b && c == x.c && d == x.d; }
82   
83           public boolean equals(Object o) {
84               if (!(o instanceof Affine)) return false;
85               Affine x = (Affine)o;
86               return a == x.a && b == x.b && c == x.c && d == x.d && e == x.e && f == x.f;
87           }
88   
89   	public static Affine rotate(float degrees) {
90   	    float s = (float)Math.sin(degrees * (float)(Math.PI / 180.0));
91   	    float c = (float)Math.cos(degrees * (float)(Math.PI / 180.0));
92   	    return new Affine(c, s, -s, c, 0, 0);
93   	}
94   
95   	/** this = this * a */
96           public Affine multiply(Affine A) {
97   	    float _a = this.a * A.a + this.b * A.c;
98   	    float _b = this.a * A.b + this.b * A.d;
99   	    float _c = this.c * A.a + this.d * A.c;
100  	    float _d = this.c * A.b + this.d * A.d;
101  	    float _e = this.e * A.a + this.f * A.c + A.e;
102  	    float _f = this.e * A.b + this.f * A.d + A.f;
103  	    a = _a; b = _b; c = _c; d = _d; e = _e; f = _f;
104              return this;
105  	}
106  
107          public void invert() {
108  	    float det = 1 / (a * d - b * c);
109  	    float _a = d * det;
110  	    float _b = -1 * b * det;
111  	    float _c = -1 * c * det;
112  	    float _d = a * det;
113  	    float _e = -1 * e * a - f * c;
114  	    float _f = -1 * e * b - f * d;
115  	    a = _a; b = _b; c = _c; d = _d; e = _e; f = _f;
116  	}
117      }
118  
119  
120      // PathTokenizer //////////////////////////////////////////////////////////////////////////////
121  
122      public static Affine parseTransform(String t) {
123          if (t == null) return null;
124          t = t.trim();
125          Affine ret = VectorGraphics.Affine.identity();
126          while (t.length() > 0) {
127              if (t.startsWith("skewX(")) {
128                  // FIXME
129                  
130              } else if (t.startsWith("shear(")) {
131                  // FIXME: nonstandard; remove this
132                  ret.multiply(VectorGraphics.Affine.shear(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
133                  
134              } else if (t.startsWith("skewY(")) {
135                  // FIXME
136                  
137              } else if (t.startsWith("rotate(")) {
138                  String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
139                  if (sub.indexOf(',') != -1) {
140                      float angle = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
141                      sub = sub.substring(sub.indexOf(',') + 1);
142                      float cx = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
143                      sub = sub.substring(sub.indexOf(',') + 1);
144                      float cy = Float.parseFloat(sub);
145                      ret.multiply(VectorGraphics.Affine.translate(cx, cy));
146                      ret.multiply(VectorGraphics.Affine.rotate(angle));
147                      ret.multiply(VectorGraphics.Affine.translate(-1 * cx, -1 * cy));
148                  } else {
149                      ret.multiply(VectorGraphics.Affine.rotate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
150                  }
151                  
152              } else if (t.startsWith("translate(")) {
153                  String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
154                  if (sub.indexOf(',') > -1) {
155                      ret.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
156                                                                   Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
157                  } else {
158                      ret.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))), 0));
159                  }
160                  
161              } else if (t.startsWith("flip(")) {
162                  String which = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
163                  ret.multiply(VectorGraphics.Affine.flip(which.equals("horizontal"), which.equals("vertical")));
164                  
165              } else if (t.startsWith("scale(")) {
166                  String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
167                  if (sub.indexOf(',') > -1) {
168                      ret.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
169                                                               Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
170                  } else {
171                      ret.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
172                                                               Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(',')))));
173                  }
174                  
175              } else if (t.startsWith("matrix(")) {
176                  // FIXME: is this mapped right?
177                  float d[] = new float[6];
178                  StringTokenizer st = new StringTokenizer(t, ",", false);
179                  for(int i=0; i<6; i++)
180                      d[i] = Float.parseFloat(st.nextToken());
181                  ret.multiply(new VectorGraphics.Affine(d[0], d[1], d[2], d[3], d[4], d[5]));
182              }
183              t = t.substring(t.indexOf(')') + 1).trim();
184          }
185          return ret;
186      }
187      
188      public static final float PX_PER_INCH = 72;
189      public static final float INCHES_PER_CM = (float)0.3937;
190      public static final float INCHES_PER_MM = INCHES_PER_CM / 10;
191  
192      public static class PathTokenizer {
193          // FIXME: check array bounds exception for improperly terminated string
194          String s;
195          int i = 0;
196          char lastCommand = 'M';
197          public PathTokenizer(String s) { this.s = s; }
198          private void consumeWhitespace() {
199              while(i < s.length() && (Character.isWhitespace(s.charAt(i)))) i++;
200              if (i < s.length() && s.charAt(i) == ',') i++;
201              while(i < s.length() && (Character.isWhitespace(s.charAt(i)))) i++;
202          }
203          public boolean hasMoreTokens() { consumeWhitespace(); return i < s.length(); }
204          public char parseCommand() {
205              consumeWhitespace();
206              char c = s.charAt(i);
207              if (!Character.isLetter(c)) return lastCommand;
208              i++;
209              return lastCommand = c;
210          }
211          public float parseFloat() {
212              consumeWhitespace();
213              int start = i;
214              float multiplier = 1;
215              for(; i < s.length(); i++) {
216                  char c = s.charAt(i);
217                  if (Character.isWhitespace(c) || c == ',' || (c == '-' && i != start)) break;
218                  if (!((c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' || c == '-')) {
219                      if (c == '%') {                                // FIXME
220                      } else if (s.regionMatches(i, "pt", 0, i+2)) { // FIXME
221                      } else if (s.regionMatches(i, "em", 0, i+2)) { // FIXME
222                      } else if (s.regionMatches(i, "pc", 0, i+2)) { // FIXME
223                      } else if (s.regionMatches(i, "ex", 0, i+2)) { // FIXME
224                      } else if (s.regionMatches(i, "mm", 0, i+2)) { i += 2; multiplier = INCHES_PER_MM * PX_PER_INCH; break;
225                      } else if (s.regionMatches(i, "cm", 0, i+2)) { i += 2; multiplier = INCHES_PER_CM * PX_PER_INCH; break;
226                      } else if (s.regionMatches(i, "in", 0, i+2)) { i += 2; multiplier = PX_PER_INCH; break;
227                      } else if (s.regionMatches(i, "px", 0, i+2)) { i += 2; break;
228                      } else if (Character.isLetter(c)) break;
229                      throw new RuntimeException("didn't expect character \"" + c + "\" in a numeric constant");
230                  }
231              }
232              if (start == i) throw new RuntimeException("FIXME");
233              return Float.parseFloat(s.substring(start, i)) * multiplier;
234          }
235      }
236  
237  
238      // Abstract Path //////////////////////////////////////////////////////////////////////////////
239  
240      /** an abstract path; may contain splines and arcs */
241      public static class VectorPath {
242  
243          // the number of vertices on this path
244  	int numvertices = 0;
245  
246          // the vertices of the path
247  	float[] x = new float[DEFAULT_PATHLEN];
248  	float[] y = new float[DEFAULT_PATHLEN];
249  
250          // the type of each edge; type[i] is the type of the edge from x[i],y[i] to x[i+1],y[i+1]
251  	byte[] type = new byte[DEFAULT_PATHLEN];
252  
253  	// bezier control points
254  	float[] c1x = new float[DEFAULT_PATHLEN];  // or rx (arcto)
255  	float[] c1y = new float[DEFAULT_PATHLEN];  // or ry (arcto)
256  	float[] c2x = new float[DEFAULT_PATHLEN];  // or x-axis-rotation (arcto)
257  	float[] c2y = new float[DEFAULT_PATHLEN];  // or large-arc << 1 | sweep (arcto)
258  
259  	boolean closed = false;
260  
261  	static final byte TYPE_MOVETO = 0;
262  	static final byte TYPE_LINETO = 1;
263  	static final byte TYPE_ARCTO = 2;
264  	static final byte TYPE_CUBIC = 3;
265  	static final byte TYPE_QUADRADIC = 4;
266  
267          /** Creates a concrete vector path transformed through the given matrix. */
268  	public RasterPath realize(Affine a) {
269  
270              RasterPath ret = new RasterPath();
271              int NUMSTEPS = 5;  // FIXME
272  	    ret.numvertices = 1;
273              ret.x[0] = (int)Math.round(a.multiply_px(x[0], y[0]));
274              ret.y[0] = (int)Math.round(a.multiply_py(x[0], y[0]));
275  
276  	    for(int i=1; i<numvertices; i++) {
277  		if (type[i] == TYPE_LINETO) {
278  		    float rx = x[i];
279  		    float ry = y[i];
280                      ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
281                      ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
282                      ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
283  
284                  } else if (type[i] == TYPE_MOVETO) {
285  		    float rx = x[i];
286  		    float ry = y[i];
287                      ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
288                      ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
289                      ret.numvertices++;
290  
291  		} else if (type[i] == TYPE_ARCTO) {
292  		    float rx = c1x[i];
293  		    float ry = c1y[i];
294  		    float phi = c2x[i];
295  		    float fa = ((int)c2y[i]) >> 1;
296  		    float fs = ((int)c2y[i]) & 1;
297  		    float x1 = x[i];
298  		    float y1 = y[i];
299  		    float x2 = x[i+1];
300  		    float y2 = y[i+1];
301  
302  		    // F.6.5: given x1,y1,x2,y2,fa,fs, compute cx,cy,theta1,dtheta
303  		    float x1_ = (float)Math.cos(phi) * (x1 - x2) / 2 + (float)Math.sin(phi) * (y1 - y2) / 2;
304  		    float y1_ = -1 * (float)Math.sin(phi) * (x1 - x2) / 2 + (float)Math.cos(phi) * (y1 - y2) / 2;
305  		    float tmp = (float)Math.sqrt((rx * rx * ry * ry - rx * rx * y1_ * y1_ - ry * ry * x1_ * x1_) /
306                                                   (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_));
307  		    float cx_ = (fa == fs ? -1 : 1) * tmp * (rx * y1_ / ry);
308  		    float cy_ = (fa == fs ? -1 : 1) * -1 * tmp * (ry * x1_ / rx);
309  		    float cx = (float)Math.cos(phi) * cx_ - (float)Math.sin(phi) * cy_ + (x1 + x2) / 2;
310  		    float cy = (float)Math.sin(phi) * cx_ + (float)Math.cos(phi) * cy_ + (y1 + y2) / 2;
311  
312                      // F.6.4 Conversion from center to endpoint parameterization
313                      float ux = 1, uy = 0, vx = (x1_ - cx_) / rx, vy = (y1_ - cy_) / ry;
314                      float det = ux * vy - uy * vx;
315                      float theta1 = (det < 0 ? -1 : 1) *
316                          (float)Math.acos((ux * vx + uy * vy) / 
317                                    ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy)));
318                      ux = (x1_ - cx_) / rx; uy = (y1_ - cy_) / ry;
319                      vx = (-1 * x1_ - cx_) / rx; vy = (-1 * y1_ - cy_) / ry;
320                      det = ux * vy - uy * vx;
321                      float dtheta = (det < 0 ? -1 : 1) *
322                          (float)Math.acos((ux * vx + uy * vy) / 
323                                    ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy)));
324                      dtheta = dtheta % (float)(2 * Math.PI);
325  
326  		    if (fs == 0 && dtheta > 0) theta1 -= 2 * PI; 
327  		    if (fs == 1 && dtheta < 0) theta1 += 2 * PI;
328  
329  		    if (fa == 1 && dtheta < 0) dtheta = 2 * PI + dtheta;
330  		    else if (fa == 1 && dtheta > 0) dtheta = -1 * (2 * PI - dtheta);
331  
332  		    // FIXME: integrate F.6.6
333  		    // FIXME: isn't quite ending where it should...
334  
335  		    // F.6.3: Parameterization alternatives
336  		    float theta = theta1;
337  		    for(int j=0; j<NUMSTEPS; j++) {
338  			float rasterx = rx * (float)Math.cos(theta) * (float)Math.cos(phi) -
339                              ry * (float)Math.sin(theta) * (float)Math.sin(phi) + cx;
340  			float rastery = rx * (float)Math.cos(theta) * (float)Math.sin(phi) +
341                              ry * (float)Math.cos(phi) * (float)Math.sin(theta) + cy;
342                          ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rasterx, rastery));
343                          ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rasterx, rastery));
344                          ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
345  			theta += dtheta / NUMSTEPS;
346  		    }
347  
348  		} else if (type[i] == TYPE_CUBIC) {
349  
350  		    float ax = x[i+1] - 3 * c2x[i] + 3 * c1x[i] - x[i];
351  		    float bx = 3 * c2x[i] - 6 * c1x[i] + 3 * x[i];
352  		    float cx = 3 * c1x[i] - 3 * x[i];
353  		    float dx = x[i];
354  		    float ay = y[i+1] - 3 * c2y[i] + 3 * c1y[i] - y[i];
355  		    float by = 3 * c2y[i] - 6 * c1y[i] + 3 * y[i];
356  		    float cy = 3 * c1y[i] - 3 * y[i];
357  		    float dy = y[i];
358  		    
359  		    for(float t=0; t<1; t += 1 / (float)NUMSTEPS) {
360  			float rx = ax * t * t * t + bx * t * t + cx * t + dx;
361  			float ry = ay * t * t * t + by * t * t + cy * t + dy;
362                          ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
363                          ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
364                          ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
365  		    }
366  
367  
368  		} else if (type[i] == TYPE_QUADRADIC) {
369  
370  		    float bx = x[i+1] - 2 * c1x[i] + x[i];
371  		    float cx = 2 * c1x[i] - 2 * x[i];
372  		    float dx = x[i];
373  		    float by = y[i+1] - 2 * c1y[i] + y[i];
374  		    float cy = 2 * c1y[i] - 2 * y[i];
375  		    float dy = y[i];
376  		    	
377                      for(float t=0; t<1; t += 1 / (float)NUMSTEPS) {
378  			float rx = bx * t * t + cx * t + dx;
379  			float ry = by * t * t + cy * t + dy;
380                          ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
381                          ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
382                          ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
383  		    }
384  
385  		}
386  
387  	    }
388              
389              if (ret.numedges > 0) ret.sort(0, ret.numedges - 1, false);
390              return ret;
391  	}
392  
393          protected void parseSingleCommandAndArguments(PathTokenizer t, char command, boolean relative) {
394              if (numvertices == 0 && command != 'm') throw new RuntimeException("first command MUST be an 'm'");
395              if (numvertices > x.length - 2) {
396                  float[] new_x = new float[x.length * 2]; System.arraycopy(x, 0, new_x, 0, x.length); x = new_x;
397                  float[] new_y = new float[y.length * 2]; System.arraycopy(y, 0, new_y, 0, y.length); y = new_y;
398              }
399              switch(command) {
400              case 'z': {
401  		int where;
402                  type[numvertices-1] = TYPE_LINETO;
403  		for(where = numvertices - 1; where > 0; where--)
404  		    if (type[where - 1] == TYPE_MOVETO) break;
405                  x[numvertices] = x[where];
406                  y[numvertices] = y[where];
407                  numvertices++;
408                  closed = true;
409                  break;
410              }
411  
412              case 'm': {
413                  if (numvertices > 0) type[numvertices-1] = TYPE_MOVETO;
414  		x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
415  		y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
416  		numvertices++;
417                  break;
418              }
419  
420              case 'l': case 'h': case 'v': {
421                  type[numvertices-1] = TYPE_LINETO;
422                  float first = t.parseFloat(), second;
423                  if (command == 'h') {
424                      second = relative ? 0 : y[numvertices - 1];
425                  } else if (command == 'v') {
426                      second = first; first = relative ? 0 : x[numvertices - 1];
427                  } else {
428                      second = t.parseFloat();
429                  }
430                  x[numvertices] = first + (relative ? x[numvertices - 1] : 0);
431                  y[numvertices] = second + (relative ? y[numvertices - 1] : 0);
432                  numvertices++;
433                  break;
434              }
435              
436              case 'a': {
437  		type[numvertices-1] = TYPE_ARCTO;
438  		c1x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
439  		c1y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
440  		c2x[numvertices-1] = (t.parseFloat() / 360) * 2 * PI;
441  		c2y[numvertices-1] = (((int)t.parseFloat()) << 1) | (int)t.parseFloat();
442  		x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
443  		y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
444                  numvertices++;
445                  break;
446              }
447  
448              case 's': case 'c': {
449                  type[numvertices-1] = TYPE_CUBIC;
450                  if (command == 'c') {
451                      c1x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
452                      c1y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
453                  } else if (numvertices > 1 && type[numvertices-2] == TYPE_CUBIC) {
454                      c1x[numvertices-1] = 2 * x[numvertices - 1] - c2x[numvertices-2];
455                      c1y[numvertices-1] = 2 * y[numvertices - 1] - c2y[numvertices-2];
456                  } else {
457                      c1x[numvertices-1] = x[numvertices-1];
458                      c1y[numvertices-1] = y[numvertices-1];
459                  }
460                  c2x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
461                  c2y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
462  		x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
463  		y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
464                  numvertices++;
465                  break;
466              }
467  
468              case 't': case 'q': {
469                  type[numvertices-1] = TYPE_QUADRADIC;
470                  if (command == 'q') {
471                      c1x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
472                      c1y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
473                  } else if (numvertices > 1 && type[numvertices-2] == TYPE_QUADRADIC) {
474                      c1x[numvertices-1] = 2 * x[numvertices - 1] - c1x[numvertices-2];
475                      c1y[numvertices-1] = 2 * y[numvertices - 1] - c1y[numvertices-2];
476                  } else {
477                      c1x[numvertices-1] = x[numvertices-1];
478                      c1y[numvertices-1] = y[numvertices-1];
479                  }
480                  x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0);
481                  y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0);
482                  numvertices++;
483                  break;
484              }
485  
486              default:
487                  // FIXME
488  	    }
489  
490              /*
491              // invariant: after this loop, no two lines intersect other than at a vertex
492              // FIXME: cleanup
493              int index = numvertices - 2;
494              for(int i=0; i<Math.min(numvertices - 3, index); i++) {
495                  for(int j = index; j < numvertices - 1; j++) {
496  
497                      // I'm not sure how to deal with vertical lines...
498                      if (x[i+1] == x[i] || x[j+1] == x[j]) continue;
499  			
500                      float islope = (y[i+1] - y[i]) / (x[i+1] - x[i]);
501                      float jslope = (y[j+1] - y[j]) / (x[j+1] - x[j]);
502                      if (islope == jslope) continue;   // parallel lines can't intersect
503  			
504                      float _x = (islope * x[i] - jslope * x[j] + y[j] - y[i]) / (islope - jslope);
505                      float _y = islope * (_x - x[i]) + y[i];
506  			
507                      if (_x > Math.min(x[i+1], x[i]) && _x < Math.max(x[i+1], x[i]) &&
508                          _x > Math.min(x[j+1], x[j]) && _x < Math.max(x[j+1], x[j])) {
509                          // FIXME: something's not right in here.  See if we can do without fracturing line 'i'.
510                          for(int k = ++numvertices; k>i; k--) { x[k] = x[k - 1]; y[k] = y[k - 1]; }
511                          x[i+1] = _x;
512                          y[i+1] = _y;
513                          x[numvertices] = x[numvertices - 1];  x[numvertices - 1] = _x;
514                          y[numvertices] = y[numvertices - 1];  y[numvertices - 1] = _y;
515                          edges[numedges++] = numvertices - 1; numvertices++;
516                          index++;
517                          break;  // actually 'continue' the outermost loop
518                      }
519                  }
520              }
521              */
522  
523  	}
524      }
525  
526  
527  
528  
529      // Rasterized Vector Path //////////////////////////////////////////////////////////////////////////////
530      
531      /** a vector path */
532      public static class RasterPath {
533  
534  	// the vertices of this path
535  	int[] x = new int[DEFAULT_PATHLEN];
536  	int[] y = new int[DEFAULT_PATHLEN];
537  	int numvertices = 0;
538  
539          /**
540           *  A list of the vertices on this path which *start* an *edge* (rather than a moveto), sorted by increasing y.
541           *  example: x[edges[1]],y[edges[1]] - x[edges[i]+1],y[edges[i]+1] is the second-topmost edge
542           *  note that if x[i],y[i] - x[i+1],y[i+1] is a MOVETO, then no element in edges will be equal to i
543           */
544  	int[] edges = new int[DEFAULT_PATHLEN];
545          int numedges = 0;
546  
547          /** translate a rasterized path */
548          public void translate(int dx, int dy) { for(int i=0; i<numvertices; i++) { x[i] += dx; y[i] += dy; } }
549  
550          /** simple quicksort, from http://sourceforge.net/snippet/detail.php?type=snippet&id=100240 */
551          int sort(int left, int right, boolean partition) {
552  	    if (partition) {
553  		int i, j, middle;
554  		middle = (left + right) / 2;
555  		int s = edges[right]; edges[right] = edges[middle]; edges[middle] = s;
556  		for (i = left - 1, j = right; ; ) {
557  		    while (y[edges[++i]] < y[edges[right]]);
558  		    while (j > left && y[edges[--j]] > y[edges[right]]);
559  		    if (i >= j) break;
560  		    s = edges[i]; edges[i] = edges[j]; edges[j] = s;
561  		}
562  		s = edges[right]; edges[right] = edges[i]; edges[i] = s;
563  		return i;
564  	    } else {
565  		if (left >= right) return 0;
566  		int p = sort(left, right, true);
567  		sort(left, p - 1, false);
568  		sort(p + 1, right, false);
569  		return 0;
570  	    }
571          }
572  
573          /** finds the x value at which the line intercepts the line y=_y */
574  	private int intercept(int i, float _y, boolean includeTop, boolean includeBottom) {
575              if (includeTop ? (_y < Math.min(y[i], y[i+1])) : (_y <= Math.min(y[i], y[i+1])))
576                  return Integer.MIN_VALUE;
577              if (includeBottom ? (_y > Math.max(y[i], y[i+1])) : (_y >= Math.max(y[i], y[i+1])))
578                  return Integer.MIN_VALUE;
579  	    return (int)Math.round((((float)(x[i + 1] - x[i])) /
580                                      ((float)(y[i + 1] - y[i])) ) * ((float)(_y - y[i])) + x[i]);
581  	}
582  
583          /** fill the interior of the path */
584  	public void fill(PixelBuffer buf, Paint paint) {
585              if (numedges == 0) return;
586  	    int y0 = y[edges[0]], y1 = y0;
587  	    boolean useEvenOdd = false;
588  
589              // we iterate over all endpoints in increasing y-coordinate order
590              for(int index = 1; index<numedges; index++) {
591                  int count = 0;
592  
593                  // we now examine the horizontal band between y=y0 and y=y1
594  		y0 = y1;
595  		y1 = y[edges[index]];
596                  if (y0 == y1) continue;
597   
598                  // within this band, we iterate over all edges
599                  int x0 = Integer.MIN_VALUE;
600                  int leftSegment = -1;
601                  while(true) {
602                      int x1 = Integer.MAX_VALUE;
603                      int rightSegment = Integer.MAX_VALUE;
604                      for(int i=0; i<numedges; i++) {
605                          if (y[edges[i]] == y[edges[i]+1]) continue; // ignore horizontal lines; they are irrelevant.
606                          // we order the segments by the x-coordinate of their midpoint;
607                          // since segments cannot intersect, this is a well-ordering
608                          int i0 = intercept(edges[i], y0, true, false);
609                          int i1 = intercept(edges[i], y1, false, true);
610                          if (i0 == Integer.MIN_VALUE || i1 == Integer.MIN_VALUE) continue;
611                          int midpoint = i0 + i1;
612                          if (midpoint < x0) continue;
613                          if (midpoint == x0 && i <= leftSegment) continue;
614                          if (midpoint > x1) continue;
615                          if (midpoint == x1 && i >= rightSegment) continue;
616                          rightSegment = i;
617                          x1 = midpoint;
618                      }
619                      if (leftSegment == rightSegment || rightSegment == Integer.MAX_VALUE) break;
620                      if (leftSegment != -1)
621                          if ((useEvenOdd && count % 2 != 0) || (!useEvenOdd && count != 0))
622                              paint.fillTrapezoid(intercept(edges[leftSegment], y0, true, true),
623                                                  intercept(edges[rightSegment], y0, true, true), y0,
624                                                  intercept(edges[leftSegment], y1, true, true),
625                                                  intercept(edges[rightSegment], y1, true, true), y1,
626                                                  buf);
627                      if (useEvenOdd) count++;
628                      else count += (y[edges[rightSegment]] < y[edges[rightSegment]+1]) ? -1 : 1;
629                      leftSegment = rightSegment; x0 = x1;
630                  }
631              }
632          }
633          
634          /** stroke the outline of the path */
635          public void stroke(PixelBuffer buf, int width, int color) { stroke(buf, width, color, null, 0, 0); }
636          public void stroke(PixelBuffer buf, int width, int color, String dashArray, int dashOffset, float segLength) {
637  
638              if (dashArray == null) {
639                  for(int i=0; i<numedges; i++)
640                      buf.drawLine((int)x[edges[i]],
641                                   (int)y[edges[i]], (int)x[edges[i]+1], (int)y[edges[i]+1], width, color, false);
642                  return;
643              }
644  
645              float ratio = 1;
646              if (segLength > 0) {
647                  float actualLength = 0;
648                  for(int i=0; i<numvertices; i++) {
649                      // skip over MOVETOs -- they do not contribute to path length
650                      if (x[i] == x[i+1] && y[i] == y[i+1]) continue;
651                      if (x[i+1] == x[i+2] && y[i+1] == y[i+2]) continue;
652                      int x1 = x[i];
653                      int x2 = x[i + 1];
654                      int y1 = y[i];
655                      int y2 = y[i + 1];
656                      actualLength += java.lang.Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
657                  }
658                  ratio = actualLength / segLength;
659              }
660              PathTokenizer pt = new PathTokenizer(dashArray);
661              Vector v = new Vector();
662              while (pt.hasMoreTokens()) v.addElement(new Float(pt.parseFloat()));
663              float[] dashes = new float[v.size() % 2 == 0 ? v.size() : 2 * v.size()];
664              for(int i=0; i<dashes.length; i++) dashes[i] = ((Float)v.elementAt(i % v.size())).floatValue();
665              float length = 0;
666              int dashpos = dashOffset;
667              boolean on = dashpos % 2 == 0;
668              for(int i=0; i<numvertices; i++) {
669                  // skip over MOVETOs -- they do not contribute to path length
670                  if (x[i] == x[i+1] && y[i] == y[i+1]) continue;
671                  if (x[i+1] == x[i+2] && y[i+1] == y[i+2]) continue;
672                  int x1 = (int)x[i];
673                  int x2 = (int)x[i + 1];
674                  int y1 = (int)y[i];
675                  int y2 = (int)y[i + 1];
676                  float segmentLength = (float)java.lang.Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
677                  int _x1 = x1, _y1 = y1;
678                  float pos = 0;
679                  do {
680                      pos = Math.min(segmentLength, pos + dashes[dashpos] * ratio);
681                      if (pos != segmentLength) dashpos = (dashpos + 1) % dashes.length;
682                      int _x2 = (int)((x2 * pos + x1 * (segmentLength - pos)) / segmentLength);
683                      int _y2 = (int)((y2 * pos + y1 * (segmentLength - pos)) / segmentLength);
684                      if (on) buf.drawLine(_x1, _y1, _x2, _y2, width, color, false);
685                      on = !on;
686                      _x1 = _x2; _y1 = _y2;
687                  } while(pos < segmentLength);
688              }
689  	}
690  
691          // FEATURE: make this faster and cache it; also deal with negative coordinates
692          public int boundingBoxWidth() {
693              int ret = 0;
694              for(int i=0; i<numvertices; i++) ret = Math.max(ret, x[i]);
695              return ret;
696          }
697  
698          // FEATURE: make this faster and cache it; also deal with negative coordinates
699          public int boundingBoxHeight() {
700              int ret = 0;
701              for(int i=0; i<numvertices; i++) ret = Math.max(ret, y[i]);
702              return ret;
703          }
704      }
705      
706      
707      // Paint //////////////////////////////////////////////////////////////////////////////
708  
709      public static interface Paint {
710  	public abstract void
711              fillTrapezoid(int tx1, int tx2, int ty1, int tx3, int tx4, int ty2, PixelBuffer buf);
712      }
713  
714      public static class SingleColorPaint implements Paint {
715          int color;
716          public SingleColorPaint(int color) { this.color = color; }
717          public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, PixelBuffer buf) {
718              buf.fillTrapezoid(x1, x2, y1, x3, x4, y2, color);
719          }
720      }
721  
722  }
723  
724  
725  
726  
727  
728  
729  
730  
731  
732      /*
733      public static abstract class GradientPaint extends Paint {
734          public GradientPaint(boolean reflect, boolean repeat, Affine gradientTransform,
735                               int[] stop_colors, float[] stop_offsets) {
736              this.reflect = reflect; this.repeat = repeat;
737              this.gradientTransform = gradientTransform;
738              this.stop_colors = stop_colors;
739              this.stop_offsets = stop_offsets;
740          }
741          Affine gradientTransform = Affine.identity();
742  	boolean useBoundingBox = false;            // FIXME not supported
743  	boolean patternUseBoundingBox = false;     // FIXME not supported
744  
745  	// it's invalid for both of these to be true
746  	boolean reflect = false;                   // FIXME not supported
747  	boolean repeat = false;                    // FIXME not supported
748  	int[] stop_colors;
749  	float[] stop_offsets;
750  
751  	public void fillTrapezoid(float tx1, float tx2, float ty1, float tx3, float tx4, float ty2, PixelBuffer buf) {
752              Affine a = buf.a;
753  	    Affine inverse = a.copy().invert();
754  	    float slope1 = (tx3 - tx1) / (ty2 - ty1);
755  	    float slope2 = (tx4 - tx2) / (ty2 - ty1);
756  	    for(float y=ty1; y<ty2; y++) {
757  		float _x1 = (y - ty1) * slope1 + tx1;
758  		float _x2 = (y - ty1) * slope2 + tx2;
759  		if (_x1 > _x2) { float _x0 = _x1; _x1 = _x2; _x2 = _x0; }
760  
761  		for(float x=_x1; x<_x2; x++) {
762  		    
763  		    float distance = isLinear ?
764  			// length of projection of <x,y> onto the gradient vector == {<x,y> \dot {grad \over |grad|}}
765  			(x * (x2 - x1) + y * (y2 - y1)) / (float)Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) :
766  			
767  			// radial form is simple! FIXME, not quite right
768  			(float)Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
769  			
770  		    // FIXME: offsets are 0..1, not 0..length(gradient)
771  		    int i = 0; for(; i<stop_offsets.length; i++) if (distance < stop_offsets[i]) break;
772  
773  		    // FIXME: handle points beyond the bounds
774  		    if (i < 0 || i >= stop_offsets.length) continue;
775  
776  		    // gradate from offsets[i - 1] to offsets[i]
777  		    float percentage = ((distance - stop_offsets[i - 1]) / (stop_offsets[i] - stop_offsets[i - 1]));
778  
779  		    int a = (int)((((stop_colors[i] >> 24) & 0xff) - ((stop_colors[i - 1] >> 24) & 0xff)) * percentage) +
780  			((stop_colors[i - 1] >> 24) & 0xff);
781  		    int r = (int)((((stop_colors[i] >> 16) & 0xff) - ((stop_colors[i - 1] >> 16) & 0xff)) * percentage) +
782  			((stop_colors[i - 1] >> 16) & 0xff);
783  		    int g = (int)((((stop_colors[i] >> 8) & 0xff)  - ((stop_colors[i - 1] >> 8) & 0xff)) * percentage) +
784  			((stop_colors[i - 1] >> 8) & 0xff);
785  		    int b = (int)((((stop_colors[i] >> 0) & 0xff)  - ((stop_colors[i - 1] >> 0) & 0xff)) * percentage) +
786  			((stop_colors[i - 1] >> 0) & 0xff);
787  		    int argb = (a << 24) | (r << 16) | (g << 8) | b;
788  		    buf.drawPoint((int)x, (int)Math.floor(y), argb);
789  		}
790  	    }
791  	}
792      }
793  
794      public static class LinearGradientPaint extends GradientPaint {
795          public LinearGradientPaint(float x1, float y1, float x2, float y2, boolean reflect, boolean repeat,
796                                     Affine gradientTransform,  int[] stop_colors, float[] stop_offsets) {
797              super(reflect, repeat, gradientTransform, stop_colors, stop_offsets);
798              this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2;
799          }
800  	float x1 = 0, y1 = 0, x2 = 300, y2 = 300;
801      }
802  
803      public static class RadialGradientPaint extends GradientPaint {
804          public RadialGradientPaint(float cx, float cy, float fx, float fy, float r, boolean reflect, boolean repeat,
805                               Affine gradientTransform, int[] stop_colors, float[] stop_offsets) {
806              super(reflect, repeat, gradientTransform, stop_colors, stop_offsets);
807              this.cx = cx; this.cy = cy; this.fx = fx; this.fy = fy; this.r = r;
808          }
809              
810  	float cx, cy, r, fx, fy;
811  
812      }
813      */
814  
815  ????????????????float??????????????????????a?????????????????????????b????????????????????????????c???????????????????????????????d??????????????????????????????????e?????????????????????????????????????f??Affine?????????float???????????????????float?????????????????????????????float???????????????????????????????????????float?????????????????????????????????????????????????float???????????????????????????????????????????????????????????float???????????????????????????????????????????????????????????????????????a???????????????????????????????????????????????????????????????????????????_a???????????????????????????????????????????????????????????????????????????????b???????????????????????????????????????????????????????????????????????????????????_b???????????????????????????????????????????????????????????????????????????????????????c???????????????????????????????????????????????????????????????????????????????????????????_c???????????????????????????????????????????????????????????????????????????????????????????????d???????????????????????????????????????????????????????????????????????????????????????????????????_d???????????????????????????????????????????????????????????????????????????????????????????????????????e???????????????????????????????????????????????????????????????????????????????????????????????????????????_e???????????????????????????????????????????????????????????????????????????????????????????????????????????????f???????????????????????????????????????????????????????????????????????????????????????????????????????????????????_f????????????????toString???????????????????????????????????????????a??????????????????????????????????????????????????????b?????????????????????????????????????????????????????????????????c????????????????????????????????????????????????????????????????????????????d???????????????????????????????????????????????????????????????????????????????????????e??????????????????????????????????????????????????????????????????????????????????????????????????f?????????Affine????????????????copy????????????????????????????????????Affine???????????????????????????????????????????a??????????????????????????????????????????????b?????????????????????????????????????????????????c????????????????????????????????????????????????????d???????????????????????????????????????????????????????e??????????????????????????????????????????????????????????f???????????????????????Affine??????????????????????????????identity??????????????????????????????????????????????????????Affine????????????????Affine???????????????????????scale?????????????????????????????float???????????????????????????????????????float??????????????????????????????????????????????????????????????Affine?????????????????????????????????????????????????????????????????????sx???????????????????????????????????????????????????????????????????????????????sy????????????????Affine???????????????????????shear?????????????????????????????float????????????????????????Affine?????????????????????????????????????????????????????degrees????????????????Affine???????????????????????translate?????????????????????????????????float???????????????????????????????????????????float??????????????????????????????????????????????????????????????????Affine?????????????????????????????????????????????????????????????????????????????????????tx?????????????????????????????????????????????????????????????????????????????????????????ty????????????????Affine???????????????????????flip????????????????????????????boolean???????????????????????????????????????????boolean??????????????????????????????????????????????????????????????????????Affine?????????????????????????????????????????????????????????????????????????????horiz???????????????????????????????????????????????????????????????????????????????????????????????????vert????????????????float??????????????????????multiply_px??????????????????????????????????float???????????????????????????????????????????float?????????????????????????????????????????????????????????????x?????????????????????????????????????????????????????????????????a?????????????????????????????????????????????????????????????????????y?????????????????????????????????????????????????????????????????????????c?????????????????????????????????????????????????????????????????????????????e?????????float???????????????multiply_py???????????????????????????float????????????????????????????????????float??????????????????????????????????????????????????????x??????????????????????????????????????????????????????????b??????????????????????????????????????????????????????????????y??????????????????????????????????????????????????????????????????d??????????????????????????????????????????????????????????????????????f????????????????boolean????????????????????????equalsIgnoringTranslation??????????????????????????????????????????????????Affine?????????????????????????????????????????????????????????????????????a??????????????????????????????????????????????????????????????????????????x????????????????????????????????????????????????????????????????????????????a?????????????????????????????????????????????????????????????????????????????????b??????????????????????????????????????????????????????????????????????????????????????x????????????????????????????????????????????????????????????????????????????????????????b?????????????????????????????????????????????????????????????????????????????????????????????c??????????????????????????????????????????????????????????????????????????????????????????????????x????????????????????????????????????????????????????????????????????????????????????????????????????c?????????????????????????????????????????????????????????????????????????????????????????????????????????d??????????????????????????????????????????????????????????????????????????????????????????????????????????????x????????????????????????????????????????????????????????????????????????????????????????????????????????????????d????????????????boolean????????????????????????equals???????????????????????????????Object???????????????????o?????????????Affine?????????????????????????Affine????????????????????????????????o????????????????????a?????????????????????????x???????????????????????????a????????????????????????????????b?????????????????????????????????????x???????????????????????????????????????b????????????????????????????????????????????c?????????????????????????????????????????????????x???????????????????????????????????????????????????c????????????????????????????????????????????????????????d?????????????????????????????????????????????????????????????x???????????????????????????????????????????????????????????????d????????????????????????????????????????????????????????????????????e?????????????????????????????????????????????????????????????????????????x???????????????????????????????????????????????????????????????????????????e????????????????????????????????????????????????????????????????????????????????f?????????????????????????????????????????????????????????????????????????????????????x???????????????????????????????????????????????????????????????????????????????????????f????????????????Affine???????????????????????rotate??????????????????????????????float??????float????????????????????????????????degrees??????float????????????????????????????????degrees?????????????????Affine????????????????????????c???????????????????????????s???????????????????????????????s??????????????????????????????????c????????????????????????????????????????Affine???????????????????????multiply????????????????????????????????Affine??????float??????????????????????????A????????????????????????????a?????????????????????????????????????????A???????????????????????????????????????????c??????float??????????????????????????A????????????????????????????b?????????????????????????????????????????A???????????????????????????????????????????d??????float??????????????????????????A????????????????????????????a?????????????????????????????????????????A???????????????????????????????????????????c??????float??????????????????????????A????????????????????????????b?????????????????????????????????????????A???????????????????????????????????????????d??????float??????????????????????????A????????????????????????????a?????????????????????????????????????????A???????????????????????????????????????????c???????????????????????????????????????????????A?????????????????????????????????????????????????e??????float??????????????????????????A????????????????????????????b?????????????????????????????????????????A???????????????????????????????????????????d???????????????????????????????????????????????A?????????????????????????????????????????????????f??????a??????????_a??????????????b??????????????????_b??????????????????????c??????????????????????????_c??????????????????????????????d??????????????????????????????????_d??????????????????????????????????????e??????????????????????????????????????????_e??????????????????????????????????????????????f??????????????????????????????????????????????????_f????????????????void?????????????????????invert??????float???????????????????????a???????????????????????????d???????????????????????????????b???????????????????????????????????c??????float?????????????????d?????????????????????det??????float??????????????????????b??????????????????????????det??????float??????????????????????c??????????????????????????det??????float?????????????????a?????????????????????det??????float??????????????????????e??????????????????????????a??????????????????????????????f??????????????????????????????????c??????float??????????????????????e??????????????????????????b??????????????????????????????f??????????????????????????????????d??????a??????????_a??????????????b??????????????????_b??????????????????????c??????????????????????????_c??????????????????????????????d??????????????????????????????????_d??????????????????????????????????????e??????????????????????????????????????????_e??????????????????????????????????????????????f??????????????????????????????????????????????????_f???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Affine??????????????????????????parseTransform?????????????t?????????t?????????????t?????????Affine??????????????????????VectorGraphics?????????????????????????????????????Affine????????????????????????????????????????????identity????????????????t?????????????????t?????????????????????????????????????????????????t????????????????????????????????????????????????????????????????????ret?????????????????????multiply??????????????????????????????VectorGraphics?????????????????????????????????????????????Affine????????????????????????????????????????????????????shear???????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????t????????????????????????t?????????????????????????????????????????????????t??????????????????????????????t??????????????????????????????????????????t??????????????????????????????????????????????????????????????t?????????????????????sub?????????????????????float????????????????????????????????????????????????????sub?????????????????????????????????????????????????????????????????????sub?????????????????????sub???????????????????????????sub?????????????????????????????????????????sub?????????????????????float?????????????????????????????????????????????????sub??????????????????????????????????????????????????????????????????sub?????????????????????sub???????????????????????????sub?????????????????????????????????????????sub?????????????????????float?????????????????????????????????????????????????sub?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????translate??????????????????????????????????????????????????????????????????cx??????????????????????????????????????????????????????????????????????cy?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????rotate???????????????????????????????????????????????????????????????angle?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????translate???????????????????????????????????????????????????????????????????????cx????????????????????????????????????????????????????????????????????????????????cy?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????rotate????????????????????????????????????????????????????????????????????????????????t????????????????????????????????????????????????????????????????????????????????????????????t????????????????????????????????????????????????????????????????????????????????????????????????????????????????t????????????????????????t??????????????????????????????t??????????????????????????????????????????t??????????????????????????????????????????????????????????????t?????????????????????sub?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????translate???????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????????t?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????translate???????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????????t????????????????????????t????????????????????????????????t????????????????????????????????????????????t????????????????????????????????????????????????????????????????t?????????????????ret?????????????????????multiply??????????????????????????????VectorGraphics?????????????????????????????????????????????Affine????????????????????????????????????????????????????flip?????????????????????????????????????????????????????????which?????????????????????????????????????????????????????????????????????????????????????which????????????????????????t??????????????????????????????t??????????????????????????????????????????t??????????????????????????????????????????????????????????????t?????????????????????sub?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????scale???????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????t?????????????????????ret?????????????????????????multiply??????????????????????????????????VectorGraphics?????????????????????????????????????????????????Affine????????????????????????????????????????????????????????scale???????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????t???????????????????????????????????????????????????????????????????????????????????????????????????????????????t????????????????????????t?????????????????????????????????????????????????????????????????float?????????????????????????????????float??????????????????????????????????????????????????????????t?????????????????????int??????????????????????????????i???????????????????????????????????i?????????????????????d???????????????????????i?????????????????????????????????????????????st?????????????????ret?????????????????????multiply????????????????????????????????????????????????????????d??????????????????????????????????????????????????????????????d????????????????????????????????????????????????????????????????????d??????????????????????????????????????????????????????????????????????????d????????????????????????????????????????????????????????????????????????????????d??????????????????????????????????????????????????????????????????????????????????????d?????????????t?????????????????t?????????????????????????????t????????????????ret?????????????????????????float???????????????????????????????PX_PER_INCH?????????????????????????float???????????????????????????????INCHES_PER_CM?????????????????????????float???????????????????????????????INCHES_PER_MM???????????????????????????????????????????????INCHES_PER_CM?????????????????????????PathTokenizer????????????????????????????????????????????????????????????????????????????????????????????????s?????????int?????????????i?????????char??????????????lastCommand????????????????PathTokenizer???????????????????????????????????????????????????s?????????????????void??????????????????????consumeWhitespace???????????????????i???????????????????????s?????????????????????????????????????????????????????????????s??????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????i?????????????????i?????????????????????s???????????????????????????????????s????????????????????????????????????????????i???????????????????????????????????????????????????????i???????????????????i???????????????????????s?????????????????????????????????????????????????????????????s??????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????i????????????????boolean????????????????????????hasMoreTokens??????????????????????????????????????????????????????????????????????i????????????????char?????????????????????parseCommand?????????????char??????????????????????s?????????????????????????????????????c??????????????????????????????????c????????????????float??????????????????????parseFloat?????????????int?????????????????????????i?????????????float???????????????????i???????????????????????????????????i?????????????????char???????????????????????????????????i????????????????????????????????????????????c??????????????????????????????????????????????????c???????????????????????????????????????????????????????????????c???????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????start????????????????????????c????????????????????????????????????c?????????????????????????????????????????????????c?????????????????????????????????????????????????????????????c?????????????????????????????????????????????????????????????????????????c?????????????????????????????????????????????????????????????????????????????????????c?????????????????????????c????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????multiplier?????????????????????????????????????????????????????????????????????????????????????????INCHES_PER_MM?????????????????????????????????????????????????????????????????????????????????????????????????????????PX_PER_INCH????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????multiplier?????????????????????????????????????????????????????????????????????????????????????????INCHES_PER_CM?????????????????????????????????????????????????????????????????????????????????????????????????????????PX_PER_INCH????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????multiplier?????????????????????????????????????????????????????????????????????????????????????????PX_PER_INCH????????????????????????????????????????????????i????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????i???????????????????????????????????????????????????c???????????????????????????????????????????????????????????????????????????????c?????????????????start??????????????????????????i?????????????????????????????????????????????????start????????????????????????????????????????????????????????i??????????????????????????????????????????????????????????????multiplier???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????VectorPath?????????????????????????????????????????????????int??????numvertices??????????????????????????????????????float??????????x??????????????????float????????????????????????DEFAULT_PATHLEN??float??????????y??????????????????float????????????????????????DEFAULT_PATHLEN????????????????????????????????????????????????????????????????????????????????????????????????????byte?????????type????????????????????byte?????????????????????????DEFAULT_PATHLEN????????????????????????????float??????????c1x????????????????????float??????????????????????????DEFAULT_PATHLEN???????????????????????????????????????????????????????????????float??????????c1y????????????????????float??????????????????????????DEFAULT_PATHLEN???????????????????????????????????????????????????????????????float??????????c2x????????????????????float??????????????????????????DEFAULT_PATHLEN????????????????????????????????????????????????????????????????????????????float??????????c2y????????????????????float??????????????????????????DEFAULT_PATHLEN???????????????????????????????????????????????????????????????????????????????????boolean??????????closed???????????????byte????????????????????TYPE_MOVETO???????????????byte????????????????????TYPE_LINETO???????????????byte????????????????????TYPE_ARCTO???????????????byte????????????????????TYPE_CUBIC???????????????byte????????????????????TYPE_QUADRADIC?????????????????????????????????????????????????????????????????????????????????????????????RasterPath????????????????????realize????????????????????????????Affine?????????????RasterPath?????????????int??????????????????????????????????????????????ret??????????numvertices?????????????ret?????????????????x????????????????????????????????????????a??????????????????????????????????????????multiply_px??????????????????????????????????????????????????????x????????????????????????????????????????????????????????????y?????????????ret?????????????????y????????????????????????????????????????a??????????????????????????????????????????multiply_py??????????????????????????????????????????????????????x????????????????????????????????????????????????????????????y??????????int???????????????????i?????????????????????numvertices??????????????????????????????????i???????type????????????i??????????????????TYPE_LINETO???????float??????????????????x????????????????????i???????float??????????????????y????????????????????i?????????????????????ret?????????????????????????x???????????????????????????ret???????????????????????????????numvertices??????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????multiply_px????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????ry?????????????????????ret?????????????????????????y???????????????????????????ret???????????????????????????????numvertices??????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????multiply_py????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????ry?????????????????????ret?????????????????????????edges???????????????????????????????ret???????????????????????????????????numedges?????????????????????????????????????????????????ret?????????????????????????????????????????????????????numvertices??????????????????????????????????????????????????????????????????????ret??????????????????????????????????????????????????????????????????????????numvertices????????????????????????????type?????????????????????????????????i???????????????????????????????????????TYPE_MOVETO???????float??????????????????x????????????????????i???????float??????????????????y????????????????????i?????????????????????ret?????????????????????????x???????????????????????????ret???????????????????????????????numvertices??????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????multiply_px????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????ry?????????????????????ret?????????????????????????y???????????????????????????ret???????????????????????????????numvertices??????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????multiply_py????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????ry?????????????????????ret?????????????????????????numvertices??????????????type???????????????????i?????????????????????????TYPE_ARCTO???????float??????????????????c1x??????????????????????i???????float??????????????????c1y??????????????????????i???????float???????????????????c2x???????????????????????i???????float????????????????????????c2y????????????????????????????i???????float????????????????????????c2y????????????????????????????i???????float??????????????????x????????????????????i???????float??????????????????y????????????????????i???????float??????????????????x????????????????????i???????float??????????????????y????????????????????i????????????????????????????????????????????????????????????????????????????float???????????????????????????????????phi???????????????????????????????????????????x1????????????????????????????????????????????????x2??????????????????????????????????????????????????????????????????????????phi??????????????????????????????????????????????????????????????????????????????????y1???????????????????????????????????????????????????????????????????????????????????????y2???????float????????????????????????????????????????phi????????????????????????????????????????????????x1?????????????????????????????????????????????????????x2???????????????????????????????????????????????????????????????????????????????phi???????????????????????????????????????????????????????????????????????????????????????y1????????????????????????????????????????????????????????????????????????????????????????????y2???????float?????????????????????????????????????rx??????????????????????????????????????????rx???????????????????????????????????????????????ry????????????????????????????????????????????????????ry?????????????????????????????????????????????????????????rx??????????????????????????????????????????????????????????????rx???????????????????????????????????????????????????????????????????y1_?????????????????????????????????????????????????????????????????????????y1_???????????????????????????????????????????????????????????????????????????????ry????????????????????????????????????????????????????????????????????????????????????ry?????????????????????????????????????????????????????????????????????????????????????????x1_???????????????????????????????????????????????????????????????????????????????????????????????x1_???????????????????????????????????????????????????rx????????????????????????????????????????????????????????rx?????????????????????????????????????????????????????????????y1_???????????????????????????????????????????????????????????????????y1_?????????????????????????????????????????????????????????????????????????ry??????????????????????????????????????????????????????????????????????????????ry???????????????????????????????????????????????????????????????????????????????????x1_?????????????????????????????????????????????????????????????????????????????????????????x1_???????float????????????????????fa??????????????????????????fs?????????????????????????????????????????tmp????????????????????????????????????????????????rx?????????????????????????????????????????????????????y1_???????????????????????????????????????????????????????????ry???????float????????????????????fa??????????????????????????fs??????????????????????????????????????????????tmp?????????????????????????????????????????????????????ry??????????????????????????????????????????????????????????x1_????????????????????????????????????????????????????????????????rx???????float??????????????????????????????????phi?????????????????????????????????????????cx_???????????????????????????????????????????????????????????????phi??????????????????????????????????????????????????????????????????????cy_?????????????????????????????????????????????????????????????????????????????x1??????????????????????????????????????????????????????????????????????????????????x2???????float??????????????????????????????????phi?????????????????????????????????????????cx_???????????????????????????????????????????????????????????????phi??????????????????????????????????????????????????????????????????????cy_?????????????????????????????????????????????????????????????????????????????y1??????????????????????????????????????????????????????????????????????????????????y2??????????????????????????????????????????????????????????????????????????????????????????????????????float?????????????????????float?????????????????????float?????????????????????float?????????????????????????????????????????????????x1_???????????????????????????????????????????????????????cx_??????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????y1_??????????????????????????????????????????????????????????????????????????????cy_?????????????????????????????????????????????????????????????????????????????????????ry?????????????????????float?????????????????????????????????ux??????????????????????????????????????vy???????????????????????????????????????????uy????????????????????????????????????????????????vx?????????????????????float?????????????????????????????????????det???????????????????????????????????????????ux????????????????????????????????????????????????vx?????????????????????????????????????????????????????uy??????????????????????????????????????????????????????????vy?????????????????????????????????????????????????????ux??????????????????????????????????????????????????????????ux???????????????????????????????????????????????????????????????uy????????????????????????????????????????????????????????????????????uy???????????????????????????????????????????????????????????????????????????????????????????vx????????????????????????????????????????????????????????????????????????????????????????????????vx?????????????????????????????????????????????????????????????????????????????????????????????????????vy??????????????????????????????????????????????????????????????????????????????????????????????????????????vy?????????????????????ux???????????????????????????x1_?????????????????????????????????cx_????????????????????????????????????????rx????????????????????????????????????????????uy??????????????????????????????????????????????????y1_????????????????????????????????????????????????????????cy_???????????????????????????????????????????????????????????????ry?????????????????????vx????????????????????????????????x1_??????????????????????????????????????cx_?????????????????????????????????????????????rx?????????????????????????????????????????????????vy????????????????????????????????????????????????????????????y1_??????????????????????????????????????????????????????????????????cy_?????????????????????????????????????????????????????????????????????????ry?????????????????????det???????????????????????????ux????????????????????????????????vy?????????????????????????????????????uy??????????????????????????????????????????vx?????????????????????float?????????????????????????????????????det???????????????????????????????????????????ux????????????????????????????????????????????????vx?????????????????????????????????????????????????????uy??????????????????????????????????????????????????????????vy?????????????????????????????????????????????????????ux??????????????????????????????????????????????????????????ux???????????????????????????????????????????????????????????????uy????????????????????????????????????????????????????????????????????uy???????????????????????????????????????????????????????????????????????????????????????????vx????????????????????????????????????????????????????????????????????????????????????????????????vx?????????????????????????????????????????????????????????????????????????????????????????????????????vy??????????????????????????????????????????????????????????????????????????????????????????????????????????vy?????????????????????dtheta??????????????????????????????dtheta???????????fs??????????????????????dtheta??????????????????????????????????theta1????????????????????????????????????????????????PI???????????fs??????????????????????dtheta??????????????????????????????????theta1????????????????????????????????????????????????PI???????????fa??????????????????????dtheta??????????????????????????????????dtheta???????????????????????????????????????????????PI????????????????????????????????????????????????????dtheta????????????????fa???????????????????????????dtheta???????????????????????????????????????dtheta??????????????????????????????????????????????????????????PI???????????????????????????????????????????????????????????????dtheta???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????float?????????????????????theta1???????????int????????????????????j??????????????????????NUMSTEPS????????????????????????????????j????float????????????????????rx?????????????????????????????????????????theta??????????????????????????????????????????????????????????????????phi?????????????????????????????ry??????????????????????????????????????????????????theta???????????????????????????????????????????????????????????????????????????phi??????????????????????????????????????????????????????????????????????????????????cx????float????????????????????rx?????????????????????????????????????????theta??????????????????????????????????????????????????????????????????phi?????????????????????????????ry??????????????????????????????????????????????????phi?????????????????????????????????????????????????????????????????????????theta??????????????????????????????????????????????????????????????????????????????????cy?????????????????????????ret?????????????????????????????x???????????????????????????????ret???????????????????????????????????numvertices??????????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????????multiply_px????????????????????????????????????????????????????????????????????????????????rasterx?????????????????????????????????????????????????????????????????????????????????????????rastery?????????????????????????ret?????????????????????????????y???????????????????????????????ret???????????????????????????????????numvertices??????????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????????multiply_py????????????????????????????????????????????????????????????????????????????????rasterx?????????????????????????????????????????????????????????????????????????????????????????rastery?????????????????????????ret?????????????????????????????edges???????????????????????????????????ret???????????????????????????????????????numedges?????????????????????????????????????????????????????ret?????????????????????????????????????????????????????????numvertices??????????????????????????????????????????????????????????????????????????ret??????????????????????????????????????????????????????????????????????????????numvertices????theta?????????????dtheta??????????????????????NUMSTEPS??????????????type???????????????????i?????????????????????????TYPE_CUBIC???????float??????????????????x????????????????????i???????????????????????????????c2x???????????????????????????????????i????????????????????????????????????????????c1x????????????????????????????????????????????????i?????????????????????????????????????????????????????x???????????????????????????????????????????????????????i???????float??????????????????????c2x??????????????????????????i???????????????????????????????????c1x???????????????????????????????????????i????????????????????????????????????????????????x??????????????????????????????????????????????????i???????float??????????????????????c1x??????????????????????????i???????????????????????????????????x?????????????????????????????????????i???????float??????????????????x????????????????????i???????float??????????????????y????????????????????i???????????????????????????????c2y???????????????????????????????????i????????????????????????????????????????????c1y????????????????????????????????????????????????i?????????????????????????????????????????????????????y???????????????????????????????????????????????????????i???????float??????????????????????c2y??????????????????????????i???????????????????????????????????c1y???????????????????????????????????????i????????????????????????????????????????????????y??????????????????????????????????????????????????i???????float??????????????????????c1y??????????????????????????i???????????????????????????????????y?????????????????????????????????????i???????float??????????????????y????????????????????i???????????float??????????????????????t???????????????????????????t???????????????????????????????????????????NUMSTEPS????float???????????????ax????????????????????t????????????????????????t????????????????????????????t????????????????????????????????bx?????????????????????????????????????t?????????????????????????????????????????t?????????????????????????????????????????????cx??????????????????????????????????????????????????t??????????????????????????????????????????????????????dx????float???????????????ay????????????????????t????????????????????????t????????????????????????????t????????????????????????????????by?????????????????????????????????????t?????????????????????????????????????????t?????????????????????????????????????????????cy??????????????????????????????????????????????????t??????????????????????????????????????????????????????dy?????????????????????????ret?????????????????????????????x???????????????????????????????ret???????????????????????????????????numvertices??????????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????????multiply_px????????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????????ry?????????????????????????ret?????????????????????????????y???????????????????????????????ret???????????????????????????????????numvertices??????????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????????multiply_py????????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????????ry?????????????????????????ret?????????????????????????????edges???????????????????????????????????ret???????????????????????????????????????numedges?????????????????????????????????????????????????????ret?????????????????????????????????????????????????????????numvertices??????????????????????????????????????????????????????????????????????????ret??????????????????????????????????????????????????????????????????????????????numvertices??????????????type???????????????????i?????????????????????????TYPE_QUADRADIC???????float??????????????????x????????????????????i???????????????????????????????c1x???????????????????????????????????i????????????????????????????????????????x??????????????????????????????????????????i???????float??????????????????????c1x??????????????????????????i???????????????????????????????????x?????????????????????????????????????i???????float??????????????????x????????????????????i???????float??????????????????y????????????????????i???????????????????????????????c1y???????????????????????????????????i????????????????????????????????????????y??????????????????????????????????????????i???????float??????????????????????c1y??????????????????????????i???????????????????????????????????y?????????????????????????????????????i???????float??????????????????y????????????????????i?????????????????????????float????????????????????????????????????t?????????????????????????????????????????t?????????????????????????????????????????????????????????NUMSTEPS????float???????????????bx????????????????????t????????????????????????t????????????????????????????cx?????????????????????????????????t?????????????????????????????????????dx????float???????????????by????????????????????t????????????????????????t????????????????????????????cy?????????????????????????????????t?????????????????????????????????????dy?????????????????????????ret?????????????????????????????x???????????????????????????????ret???????????????????????????????????numvertices??????????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????????multiply_px????????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????????ry?????????????????????????ret?????????????????????????????y???????????????????????????????ret???????????????????????????????????numvertices??????????????????????????????????????????????????????????????????a????????????????????????????????????????????????????????????????????multiply_py????????????????????????????????????????????????????????????????????????????????rx????????????????????????????????????????????????????????????????????????????????????ry?????????????????????????ret?????????????????????????????edges???????????????????????????????????ret???????????????????????????????????????numedges?????????????????????????????????????????????????????ret?????????????????????????????????????????????????????????numvertices??????????????????????????????????????????????????????????????????????????ret??????????????????????????????????????????????????????????????????????????????numvertices?????????????????ret?????????????????????numedges???????????????????????????????????ret???????????????????????????????????????sort???????????????????????????????????????????????ret???????????????????????????????????????????????????numedges????????????????????ret???????????????????void????????????????????????parseSingleCommandAndArguments???????????????????????????????????????????????????????PathTokenizer????????????????????????????????????????????????????????????????????????char??????????????????????????????????????????????????????????????????????????????????????boolean?????????????????????????????????????command?????????????????float?????????????????????????????????????float?????????????????????????????????????????????????????????????????????????????????new_x??????????????????????????????????????????????????????????????????????????????????????????????????????????new_x?????????????????float?????????????????????????????????????float?????????????????????????????????????????????????????????????????????????????????new_y??????????????????????????????????????????????????????????????????????????????????????????????????????????new_y????????????????????command???int???????where????????????????????????????????where???????????????????????????????????????????where????????????????where????????????????????????????????????where????????????????????????????????????where????????????????????t??????????????????????parseFloat??????????????????????????????????????relative????????????????????t??????????????????????parseFloat??????????????????????????????????????relative?????????????????float?????????????????float???????????????????????????????t?????????????????????????????????parseFloat?????????????????????command?????????????????????second??????????????????????????????relative????????????????????????????command?????????????????????second??????????????????????????????first?????????????????????????????????????first?????????????????????????????????????????????relative?????????????????????second??????????????????????????????t????????????????????????????????parseFloat??????????????????????????????????first???????????????????????????????????????????relative??????????????????????????????????second????????????????????????????????????????????relative????????????????????????t??????????????????????????parseFloat??????????????????????????????????????????relative????????????????????????t??????????????????????????parseFloat??????????????????????????????????????????relative?????????????????????????t???????????????????????????parseFloat?????????????????????????????????????????????????????PI???????????????????????????????t?????????????????????????????????parseFloat????????????????????????????????????????????????????????????t??????????????????????????????????????????????????????????????parseFloat????????????????????t??????????????????????parseFloat??????????????????????????????????????relative????????????????????t??????????????????????parseFloat??????????????????????????????????????relative?????????????????????command??????????????????????????????????????????t????????????????????????????????????????????parseFloat????????????????????????????????????????????????????????????relative??????????????????????????????????????????t????????????????????????????????????????????parseFloat????????????????????????????????????????????????????????????relative??????????????????????????????????????t????????????????????????????????????????parseFloat????????????????????????????????????????????????????????relative??????????????????????????????????????t????????????????????????????????????????parseFloat????????????????????????????????????????????????????????relative????????????????????t??????????????????????parseFloat??????????????????????????????????????relative????????????????????t??????????????????????parseFloat??????????????????????????????????????relative?????????????????????command??????????????????????????????????????????t????????????????????????????????????????????parseFloat????????????????????????????????????????????????????????????relative??????????????????????????????????????????t????????????????????????????????????????????parseFloat????????????????????????????????????????????????????????????relative??????????????????????????????????t????????????????????????????????????parseFloat????????????????????????????????????????????????????relative??????????????????????????????????t????????????????????????????????????parseFloat????????????????????????????????????????????????????relative???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RasterPath????????????????????????????????int????????x????????????????int????????????????????DEFAULT_PATHLEN??int????????y????????????????int????????????????????DEFAULT_PATHLEN??int??????numvertices????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????int????????edges????????????????????int????????????????????????DEFAULT_PATHLEN?????????int?????????????numedges???????????????????????????????????????????????????????????void?????????????????????translate???????????????????????????????int???????????????????????????????????????int?????????????????????????????????????????????????????int??????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????numvertices?????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????x??????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????dx????????????????????????????????????????????????????????????????????????????????????????????????y??????????????????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????????????????dy????????????????????????????????????????????????????????????????????????????????????????????????????????????????int?????????????sort??????????????????int????????????????????????????int???????????????????????????????????????boolean??????????partition???int???int???int???middle?????????????left????????????????????right???int???????????edges?????????????????right?????????????????????????edges???????????????????????????????right????????????????????????????????????????edges??????????????????????????????????????????????middle???????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????middle???????????????????????????????????????????????????????????????????????s????????i????????????left??????????????????????j??????????????????????????right??????????????y????????????????edges????????????????????????i??????????????????????????????y????????????????????????????????edges??????????????????????????????????????right??????????????j??????????????????left??????????????????????????y????????????????????????????edges????????????????????????????????????j??????????????????????????????????????????y????????????????????????????????????????????edges??????????????????????????????????????????????????right???????????i????????????????j???????s???????????edges?????????????????i?????????????????????edges???????????????????????????i????????????????????????????????edges??????????????????????????????????????j??????????????????????????????????????????edges????????????????????????????????????????????????j?????????????????????????????????????????????????????s???s???????edges?????????????right?????????????????????edges???????????????????????????right????????????????????????????????????edges??????????????????????????????????????????i??????????????????????????????????????????????edges????????????????????????????????????????????????????i?????????????????????????????????????????????????????????s??????????i???????left???????????????right???int???????????sort????????????????left??????????????????????right???sort????????left??????????????p???sort????????p???????????????right??????????????????????????????????????????????????????????????????????????????????????int??????????????intercept????????????????????????int???????????????????????????????float?????????????????????????????????????????boolean?????????????????????????????????????????????????????????????boolean?????????????????includeTop???????????????????????????????_y?????????????????????????????????????????????y???????????????????????????????????????????????i???????????????????????????????????????????????????y?????????????????????????????????????????????????????i???????????????????????????????????????????????????????????????_y??????????????????????????????????????????????????????????????????????????????y????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????y??????????????????????????????????????????????????????????????????????????????????????i?????????????????includeBottom??????????????????????????????????_y????????????????????????????????????????????????y??????????????????????????????????????????????????i??????????????????????????????????????????????????????y????????????????????????????????????????????????????????i??????????????????????????????????????????????????????????????????_y?????????????????????????????????????????????????????????????????????????????????y???????????????????????????????????????????????????????????????????????????????????i???????????????????????????????????????????????????????????????????????????????????????y?????????????????????????????????????????????????????????????????????????????????????????i???????????????????????????????????????x?????????????????????????????????????????i??????????????????????????????????????????????????x????????????????????????????????????????????????????i??????????????????????????????????????????????y????????????????????????????????????????????????i?????????????????????????????????????????????????????????y???????????????????????????????????????????????????????????i?????????????????????????????????????????????????????????????????????????????_y??????????????????????????????????????????????????????????????????????????????????y????????????????????????????????????????????????????????????????????????????????????i???????????????????????????????????????????????????????????????????????????????????????????x?????????????????????????????????????????????????????????????????????????????????????????????i??????????????????????????????????????????????????????void??????????????fill???????????????????PixelBuffer????????????????????????????????????Paint?????????????????numedges??????int??????int???????????????y?????????????????edges?????????????????????????????????y0??????boolean???????????????????????????????????????????????????????????????????????????????????????????????int????????????????????????????????index??????????????????????????????????????numedges????????????????????????????????????????????????index?????????????????int???????????????????????????????????????????????????????????????????????????????y0????????y1???y1????????y??????????edges????????????????index?????????????????????y0???????????????????????????y1????????????????????????????????????????????????????????????????????????????????int?????????????????int?????????????????????int?????????????????????int?????????????????????????int??????????????????????????????????i????????????????????????????????????numedges??????????????????????????????????????????????i?????????????????????????????y???????????????????????????????edges?????????????????????????????????????i????????????????????????????????????????????y??????????????????????????????????????????????edges????????????????????????????????????????????????????i??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????int??????????????????????????????????intercept????????????????????????????????????????????edges??????????????????????????????????????????????????i??????????????????????????????????????????????????????y0?????????????????????????int??????????????????????????????????intercept????????????????????????????????????????????edges??????????????????????????????????????????????????i??????????????????????????????????????????????????????y1?????????????????????????????i0????????????????????????????????????????????????????????i1?????????????????????????int????????????????????????????????????????i0?????????????????????????????????????????????i1?????????????????????????????midpoint????????????????????????????????????????x0?????????????????????????????midpoint?????????????????????????????????????????x0???????????????????????????????????????????????i????????????????????????????????????????????????????leftSegment?????????????????????????????midpoint????????????????????????????????????????x1?????????????????????????????midpoint?????????????????????????????????????????x1???????????????????????????????????????????????i????????????????????????????????????????????????????rightSegment?????????????????????????rightSegment????????????????????????????????????????i?????????????????????????x1??????????????????????????????midpoint?????????????????????????leftSegment????????????????????????????????????????rightSegment????????????????????????????????????????????????????????rightSegment?????????????????????????leftSegment??????????????????????????????useEvenOdd????????????????????????????????????????????count?????????????????????????????????????????????????????????????????useEvenOdd???????????????????????????????????????????????????????????????????????????????count?????????????????????????????paint???????????????????????????????????fillTrapezoid?????????????????????????????????????????????????intercept???????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????leftSegment???????????????????????????????????????????????????????????????????????????????y0?????????????????????????????????????????????????intercept???????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????rightSegment????????????????????????????????????????????????????????????????????????????????y0?????????????????????????????????????????????????????????????????????????????????????????????????y0?????????????????????????????????????????????????intercept???????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????leftSegment???????????????????????????????????????????????????????????????????????????????y1?????????????????????????????????????????????????intercept???????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????rightSegment????????????????????????????????????????????????????????????????????????????????y1?????????????????????????????????????????????????????????????????????????????????????????????????y1?????????????????????????????????????????????????buf?????????????????????????useEvenOdd?????????????????????????????????????count??????????????????????????count????????????????????????????????????y??????????????????????????????????????edges????????????????????????????????????????????rightSegment?????????????????????????????????????????????????????????????y???????????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????????rightSegment?????????????????????leftSegment???????????????????????????????????rightSegment?????????????????????????????????????????????????x0??????????????????????????????????????????????????????x1??????????????????????????????????????????????????????????????void?????????????????????stroke????????????????????????????PixelBuffer?????????????????????????????????????????????int????????????????????????????????????????????????????????int?????????????????????????????????????????????????????????????????????stroke????????????????????????????????????????????????????????????????????????????buf?????????????????????????????????????????????????????????????????????????????????width????????????????????????????????????????????????????????????????????????????????????????color????????????????void?????????????????????stroke????????????????????????????PixelBuffer?????????????????????????????????????????????int????????????????????????????????????????????????????????int?????????????????????????????????????????????????????????????????????????????????????int?????????????????????????????????????????????????????????????????????????????????????????????????????float?????????????????dashArray?????????????????????int??????????????????????????????i????????????????????????????????numedges??????????????????????????????????????????i?????????????????????buf?????????????????????????drawLine???????????????????????????????????????x?????????????????????????????????????????edges???????????????????????????????????????????????i???????????????????????????????????????y?????????????????????????????????????????edges???????????????????????????????????????????????i?????????????????????????????????????????????????????????x???????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????i?????????????????????????????????????????????????????????????????????????????y???????????????????????????????????????????????????????????????????????????????edges?????????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????????????width???????????????????????????????????????????????????????????????????????????????????????????????????color?????????????float?????????????????segLength?????????????????float?????????????????????int??????????????????????????????i????????????????????????????????numvertices?????????????????????????????????????????????i???????????????????????????????????????????????????????????????????????????????????????????????????????????x???????????????????????????i?????????????????????????????????x???????????????????????????????????i???????????????????????????????????????????y?????????????????????????????????????????????i???????????????????????????????????????????????????y?????????????????????????????????????????????????????i?????????????????????????x???????????????????????????i???????????????????????????????????x?????????????????????????????????????i?????????????????????????????????????????????y???????????????????????????????????????????????i???????????????????????????????????????????????????????y?????????????????????????????????????????????????????????i?????????????????????int??????????????????????????????x????????????????????????????????i?????????????????????int??????????????????????????????x????????????????????????????????i?????????????????????int??????????????????????????????y????????????????????????????????i?????????????????????int??????????????????????????????y????????????????????????????????i?????????????????????actualLength??????????????????????????????????????????????????????????x2???????????????????????????????????????????????????????????????x1??????????????????????????????????????????????????????????????????????x2???????????????????????????????????????????????????????????????????????????x1??????????????????????????????????????????????????????????????????????????????????y2???????????????????????????????????????????????????????????????????????????????????????y1??????????????????????????????????????????????????????????????????????????????????????????????y2???????????????????????????????????????????????????????????????????????????????????????????????????y1?????????????????ratio?????????????????????????actualLength????????????????????????????????????????segLength?????????????PathTokenizer????????????????????????????????????PathTokenizer??????????????????????????????????????????????????dashArray????????????????????pt???????????????????????hasMoreTokens????????????????????????????????????????v???????????????????????????????????????????????????????????????pt??????????????????????????????????????????????????????????????????parseFloat?????????????float??????????????????????????????????float????????????????????????????????????????v????????????????????????????????????????????????????????????v???????????????????????????????????????????????????????????????????????????v?????????????????int??????????????????????????i????????????????????????????dashes???????????????????????????????????????????i????????????????????????????????????????????????dashes???????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????v????????????????????????????????????????????????????????????????????????????????i????????????????????????????????????????????????????????????????????????????????????v?????????????float?????????????int???????????????????????????dashOffset?????????????boolean??????????????????????????dashpos?????????????????int??????????????????????????i????????????????????????????numvertices?????????????????????????????????????????i???????????????????????????????????????????????????????????????????????????????????????????????????x???????????????????????i?????????????????????????????x???????????????????????????????i???????????????????????????????????????y?????????????????????????????????????????i???????????????????????????????????????????????y?????????????????????????????????????????????????i?????????????????????x???????????????????????i???????????????????????????????x?????????????????????????????????i?????????????????????????????????????????y???????????????????????????????????????????i???????????????????????????????????????????????????y?????????????????????????????????????????????????????i?????????????????int???????????????????????????????x?????????????????????????????????i?????????????????int???????????????????????????????x?????????????????????????????????i?????????????????int???????????????????????????????y?????????????????????????????????i?????????????????int???????????????????????????????y?????????????????????????????????i?????????????????float???????????????????????????????????????????????????????????????????x2????????????????????????????????????????????????????????????????????????x1???????????????????????????????????????????????????????????????????????????????x2????????????????????????????????????????????????????????????????????????????????????x1???????????????????????????????????????????????????????????????????????????????????????????y2????????????????????????????????????????????????????????????????????????????????????????????????y1???????????????????????????????????????????????????????????????????????????????????????????????????????y2????????????????????????????????????????????????????????????????????????????????????????????????????????????y1?????????????????int?????????????????int???????????????????????????x1?????????????????????????????????????y1?????????????????float?????????????????????pos????????????????????????????????????segmentLength???????????????????????????????????????????????????pos?????????????????????????????????????????????????????????dashes????????????????????????????????????????????????????????????????dashpos???????????????????????????????????????????????????????????????????????????ratio?????????????????????????pos????????????????????????????????segmentLength???????????????????????????????????????????????dashpos??????????????????????????????????????????????????????????dashpos?????????????????????????????????????????????????????????????????????????dashes?????????????????????int??????????????????????????????????????x2???????????????????????????????????????????pos?????????????????????????????????????????????????x1???????????????????????????????????????????????????????segmentLength???????????????????????????????????????????????????????????????????????pos???????????????????????????????????????????????????????????????????????????????segmentLength?????????????????????int??????????????????????????????????????y2???????????????????????????????????????????pos?????????????????????????????????????????????????y1???????????????????????????????????????????????????????segmentLength???????????????????????????????????????????????????????????????????????pos???????????????????????????????????????????????????????????????????????????????segmentLength?????????????????????????on?????????????????????????????buf?????????????????????????????????drawLine??????????????????????????????????????????_x1???????????????????????????????????????????????_y1????????????????????????????????????????????????????_x2?????????????????????????????????????????????????????????_y2??????????????????????????????????????????????????????????????width?????????????????????????????????????????????????????????????????????color?????????????????????on???????????????????????????on?????????????????????_x1???????????????????????????_x2????????????????????????????????_y1??????????????????????????????????????_y2?????????????????????????pos???????????????????????????????segmentLength???????????????????????????????????????????????????????????????????????????????????????????????????????int????????????????????boundingBoxWidth?????????????int?????????????????int??????????????????????????i????????????????????????????numvertices?????????????????????????????????????????i??????????????????????????????????????????????ret?????????????????????????????????????????????????????????????ret??????????????????????????????????????????????????????????????????x????????????????????????????????????????????????????????????????????i????????????????????ret???????????????????????????????????????????????????????????????????????????????????????????????????????int????????????????????boundingBoxHeight?????????????int?????????????????int??????????????????????????i????????????????????????????numvertices?????????????????????????????????????????i??????????????????????????????????????????????ret?????????????????????????????????????????????????????????????ret??????????????????????????????????????????????????????????????????y????????????????????????????????????????????????????????????????????i????????????????????ret?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Paint??????????????????void?????????????fillTrapezoid???????????????????????????int????????????????????????????????????int?????????????????????????????????????????????int??????????????????????????????????????????????????????int???????????????????????????????????????????????????????????????int????????????????????????????????????????????????????????????????????????int?????????????????????????????????????????????????????????????????????????????????PixelBuffer?????????????????????????SingleColorPaint?????????????????????????????????????????????????????Paint?????????int?????????????color????????????????SingleColorPaint?????????????????????????????????int???????????????????????????????????????????????????????????color????????????????void?????????????????????fillTrapezoid???????????????????????????????????int???????????????????????????????????????????int???????????????????????????????????????????????????int???????????????????????????????????????????????????????????int???????????????????????????????????????????????????????????????????int???????????????????????????????????????????????????????????????????????????int???????????????????????????????????????????????????????????????????????????????????PixelBuffer?????????????buf?????????????????fillTrapezoid???????????????????????????????x1???????????????????????????????????x2???????????????????????????????????????y1???????????????????????????????????????????x3???????????????????????????????????????????????x4???????????????????????????????????????????????????y2???????????????????????????????????????????????????????color???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????