1
6 import java.awt.*;
7 import java.awt.geom.*;
8 import java.util.*;
9
10
11 public abstract class TickedStroke extends SavableStroke {
12 static double tol = 0.5;
13
14 static int PENDOWN = 1;
15 static int PENUP = 2;
16 static int LEFT = 4;
17 static int RIGHT = 8;
18
19 public double thickness;
20 public double ticklength;
21 int flip = 1;
22
23 double[] lengths;
24 int[] actions;
25 int partcnt;
26
27 public TickedStroke(double thickness) {
28 super(thickness);
29 }
30
31 Vector heads = new Vector();
32 Vector tails = new Vector();
33
34 public void setFlip(boolean val) {
35 if (val) flip = -1;
36 else flip = 1;
37 }
38
39 public Shape createStrokedShape(Shape p) {
40
41 PathIterator path = p.getPathIterator(new AffineTransform(),tol);
42 GeneralPath res = new GeneralPath();
43
44
45
46 double[] points;
47 double[] current = null;
48 int type;
49 double[] start = null;
50
51 heads.clear();
52 tails.clear();
53
54 double dist;
55
56 double[] anchor;
57 double[] end;
58
59 int curpart = 0;
60 double phase = lengths[0];
61 boolean pendown = true;
62
63
64 for (;!path.isDone();path.next()) {
65
66 points = new double[2];
67 type = path.currentSegment(points);
68
69 switch (type) {
70 case PathIterator.SEG_MOVETO:
71 res.moveTo((float)points[0],(float)points[1]);
72 start = points;
73 current = points;
74 break;
75 case PathIterator.SEG_CLOSE:
76 points = start;
77 case PathIterator.SEG_LINETO:
78 dist = Math.sqrt((points[0]-current[0])*(points[0]-current[0]) +
79 (points[1]-current[1])*(points[1]-current[1]));
80 while (phase < dist) {
81 anchor = new double[2];
82 anchor[0] = current[0] + phase*(points[0]-current[0])/dist;
83 anchor[1] = current[1] + phase*(points[1]-current[1])/dist;
84
85 if (pendown)
86 res.lineTo((float)anchor[0],(float)anchor[1]);
87 else if ((actions[curpart]&PENDOWN) !=0)
88 res.moveTo((float)anchor[0],(float)anchor[1]);
89 if ((actions[curpart]&PENDOWN) !=0) pendown = true;
90 if ((actions[curpart]&PENUP) !=0) pendown = false;
91
92 if ((actions[curpart]&(LEFT|RIGHT)) !=0) {
93 if((actions[curpart]&LEFT) !=0) {
94 end = new double[2];
95 end[0] = anchor[0] - flip*ticklength*(points[1]-current[1])/dist;
96 end[1] = anchor[1] + flip*ticklength*(points[0]-current[0])/dist;
97 heads.add(end);
98 } else heads.add(anchor);
99 if((actions[curpart]&RIGHT) !=0) {
100 end = new double[2];
101 end[0] = anchor[0] + flip*ticklength*(points[1]-current[1])/dist;
102 end[1] = anchor[1] - flip*ticklength*(points[0]-current[0])/dist;
103 tails.add(end);
104 } else tails.add(anchor);
105 }
106
107 dist -= phase;
108 curpart = (curpart+1)%partcnt;
109 phase = lengths[curpart];
110 current = anchor;
111 }
112
113
114 if (dist>0) {
115
116
117 if (pendown)
118 res.lineTo((float)points[0],(float)points[1]);
119
120
121 phase -= dist;
122 current = points;
123 }
124 }
125 }
126
127 for (int i=0;i<heads.size();i++) {
128 res.moveTo((float)((double[])heads.elementAt(i))[0],(float)((double[])heads.elementAt(i))[1]);
129 res.lineTo((float)((double[])tails.elementAt(i))[0],(float)((double[])tails.elementAt(i))[1]);
130 }
131
132 return(linestroke.createStrokedShape(res));
133 }
134 }
135