blob: 3cf835c3ca80cf1ee1dcbd7dd29630ee83013cc4 [file] [log] [blame]
caryclarkdac1d172014-06-17 05:15:38 -07001<html>
2<head>
3<div height="0" hidden="true">
caryclarkdac1d172014-06-17 05:15:38 -07004
caryclark26ad22a2015-10-16 09:03:38 -07005<div id="skpwww_gorcraft_ru_1">
6seg=1 {{{{1170, 4559}, {1176, 4559}, {1176, 4565}}}, 0.707106769f}
7seg=2 {{{1176, 4565}, {1176, 4590}}}
8seg=3 {{{{1176, 4590}, {1176, 4595}, {1171, 4595}}}, 0.707106769f}
9seg=4 {{{1171, 4595}, {83, 4595}}}
10seg=5 {{{{83, 4595}, {78.0086746f, 4595}, {78, 4590.00586f}}}, 0.707720578f}
11seg=6 {{{78, 4590.00586f}, {78, 4565}}}
12seg=7 {{{{78, 4565}, {78, 4559}, {84, 4559}}}, 0.707106769f}
13seg=8 {{{84, 4559}, {1170, 4559}}}
caryclark27c8eb82015-07-06 11:38:33 -070014op union
caryclark26ad22a2015-10-16 09:03:38 -070015seg=9 {{{78, 4590}, {78, 4565}}}
16seg=10 {{{{78, 4565}, {78, 4559}, {84, 4559}}}, 0.707106769f}
17seg=11 {{{84, 4559}, {158, 4559}}}
18seg=12 {{{158, 4559}, {158, 4596}}}
19seg=13 {{{158, 4596}, {84, 4596}}}
20seg=14 {{{{84, 4596}, {78, 4596}, {78, 4590}}}, 0.707106769f}
21debugShowConicLineIntersection wtTs[0]=1 {{{{1170,4559}, {1176,4559}, {1176,4565}}}, 0.707106769} {{1176,4565}} wnTs[0]=0 {{{1176,4565}, {1176,4590}}}
22debugShowConicLineIntersection wtTs[0]=0 {{{{1170,4559}, {1176,4559}, {1176,4565}}}, 0.707106769} {{1170,4559}} wnTs[0]=1 {{{84,4559}, {1170,4559}}}
23debugShowConicLineIntersection wtTs[0]=0 {{{{1176,4590}, {1176,4595}, {1171,4595}}}, 0.707106769} {{1176,4590}} wnTs[0]=1 {{{1176,4565}, {1176,4590}}}
24debugShowConicLineIntersection wtTs[0]=1 {{{{1176,4590}, {1176,4595}, {1171,4595}}}, 0.707106769} {{1171,4595}} wnTs[0]=0 {{{1171,4595}, {83,4595}}}
25debugShowConicLineIntersection wtTs[0]=0 {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{83,4595}} wnTs[0]=1 {{{1171,4595}, {83,4595}}}
26debugShowConicLineIntersection wtTs[0]=1 {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{78,4590.00586}} wnTs[0]=0 {{{78,4590.00586}, {78,4565}}}
27debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590.00586}, {78,4565}}}
28debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {1170,4559}}}
29debugShowLineIntersection wtTs[0]=0.972972973 {{{158,4559}, {158,4596}}} {{158,4595}} wnTs[0]=0.931066 {{{1171,4595}, {83,4595}}}
30SkOpSegment::addT insert t=0.931066176 segID=4 spanID=29
31SkOpSegment::addT insert t=0.972972973 segID=12 spanID=30
32debugShowConicLineIntersection no intersect {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{{1171,4595}, {83,4595}}}
33debugShowConicLineIntersection no intersect {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{{78,4590}, {78,4565}}}
34id=1 1=(0,1) [4,2] id=2 2=(0,0.5) [1] 4=(0.5,1) [1]
35id=1 1=(0,0.5) [4,2] 3=(0.5,1) [4] id=2 2=(0,0.5) [1] 4=(0.5,1) [3,1]
36id=1 1=(0,0.5) [2] 3=(0.5,1) [6,4] id=2 2=(0,0.5) [1] 4=(0.5,0.75) [3] 6=(0.75,1) [3]
37id=1 3=(0.5,1) [6,4] id=2 4=(0.5,0.75) [3] 6=(0.75,1) [3]
38id=1 3=(0.5,0.75) [6,4] 5=(0.75,1) [6] id=2 4=(0.5,0.75) [3] 6=(0.75,1) [5,3]
39id=1 3=(0.5,0.75) [4] 5=(0.75,1) [10,6] id=2 4=(0.5,0.75) [3] 6=(0.75,0.875) [5] 10=(0.875,1) [5]
40id=1 5=(0.75,1) [10,6] id=2 6=(0.75,0.875) [5] 10=(0.875,1) [5]
41id=1 5=(0.75,0.875) [10,6] 7=(0.875,1) [10] id=2 6=(0.75,0.875) [5] 10=(0.875,1) [7,5]
42id=1 5=(0.75,0.875) [10] 7=(0.875,1) [10] id=2 10=(0.875,1) [7,5]
43id=1 7=(0.875,1) [16,10] id=2 10=(0.875,0.9375) [7] 16=(0.9375,1) [7]
44id=1 7=(0.875,0.9375) [16,10] 9=(0.9375,1) [16] id=2 10=(0.875,0.9375) [7] 16=(0.9375,1) [9,7]
45id=1 7=(0.875,0.9375) [16] 9=(0.9375,1) [16] id=2 16=(0.9375,1) [9,7]
46id=1 9=(0.9375,1) [20,16] id=2 16=(0.9375,0.96875) [9] 20=(0.96875,1) [9]
47id=1 9=(0.9375,0.96875) [20,16] 11=(0.96875,1) [20] id=2 16=(0.9375,0.96875) [9] 20=(0.96875,1) [11,9]
48id=1 9=(0.9375,0.96875) [20] 11=(0.96875,1) [20] id=2 20=(0.96875,1) [11,9]
49id=1 11=(0.96875,1) [24,20] id=2 20=(0.96875,0.984375) [11] 24=(0.984375,1) [11]
50id=1 11=(0.96875,0.984375) [24,20] 13=(0.984375,1) [24] id=2 20=(0.96875,0.984375) [11] 24=(0.984375,1) [13,11]
51id=1 11=(0.96875,0.984375) [24] 13=(0.984375,1) [24] id=2 24=(0.984375,1) [13,11]
52id=1 13=(0.984375,1) [28,24] id=2 24=(0.984375,0.992188) [13] 28=(0.992188,1) [13]
53id=1 13=(0.984375,0.992188) [24] 15=(0.992188,1) [28] id=2 24=(0.984375,0.992188) [13] 28=(0.992188,1) [15]
54id=1 15=(0.992188,1) [28] id=2 28=(0.992188,1) [15]
55id=1 15=(0.992188,1) [32,28] id=2 28=(0.992188,0.996094) [15] 32=(0.996094,1) [15]
56id=1 15=(0.992188,0.996094) [28] 17=(0.996094,1) [28,32] id=2 28=(0.992188,0.996094) [17,15] 32=(0.996094,1) [17]
57id=1 17=(0.996094,1) [32] id=2 32=(0.996094,1) [17]
58id=1 17=(0.996094,1) [36,32] id=2 32=(0.996094,0.998047) [17] 36=(0.998047,1) [17]
59id=1 19=(0.998047,1) [36] id=2 36=(0.998047,1) [19]
60id=1 19=(0.998047,1) [38,36] id=2 36=(0.998047,0.999023) [19] 38=(0.999023,1) [19]
61setPerp t=0.998046875 cPt=(78.0000229,4590.01658) == oppT=0.998483762 fPerpPt=(78.0000301,4590.01658)
62setPerp t=0.999023438 cPt=(78.0000057,4590.00829) == oppT=0.99965636 fPerpPt=(78.0000048,4590.00829)
63setPerp t=0.999023438 cPt=(78.0000168,4590.01276) == oppT=0.998496341 fPerpPt=(78.0000136,4590.01276)
64setPerp t=0.998046875 cPt=(78.0000229,4590.01658) == oppT=0.998483762 fPerpPt=(78.0000301,4590.01658)
65setPerp t=0.999023438 cPt=(78.0000057,4590.00829) == oppT=0.99965636 fPerpPt=(78.0000048,4590.00829)
66setPerp t=0.999023438 cPt=(78.0000168,4590.01276) == oppT=0.998496341 fPerpPt=(78.0000136,4590.01276)
67setPerp t=0.999339899 cPt=(78.0000103,4590.01053) == oppT=0.998759893 fPerpPt=(78.0000092,4590.01053)
68id=1 21=(0.99934,0.99934) [36] id=2 36=(0.99876,0.99876) [21]
69debugShowConicIntersection wtTs[0]=0.999339899 {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{78.0000076,4590.01074}} wnTs[0]=0.99876 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769}
70SkOpSegment::addT insert t=0.999339899 segID=5 spanID=31
71SkOpSegment::addT insert t=0.998759893 segID=14 spanID=32
72debugShowLineIntersection wtTs[0]=0 {{{78,4590}, {78,4565}}} {{78,4590}} wtTs[1]=1 {{78,4565}} wnTs[0]=0.00023432 {{{78,4590.00586}, {78,4565}}} wnTs[1]=1
73SkOpSegment::addT insert t=0.000234320081 segID=6 spanID=33
74debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590.00586}, {78,4565}}}
75debugShowConicLineIntersection wtTs[0]=1 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{78,4590}} wnTs[0]=0.00023432 {{{78,4590.00586}, {78,4565}}}
76debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590}, {78,4565}}}
77id=1 1=(0,1) [4,2] id=2 2=(0,0.5) [1] 4=(0.5,1) [1]
78id=1 1=(0,0.5) [4,2] 3=(0.5,1) [2,4] id=2 2=(0,0.5) [3,1] 4=(0.5,1) [3,1]
79id=1 1=(0,0.5) [6,4,2] 3=(0.5,1) [6,4] id=2 2=(0,0.25) [1] 6=(0.25,0.5) [1,3] 4=(0.5,1) [3,1]
80id=1 1=(0,0.25) [6,2] 5=(0.25,0.5) [2,4,6] 3=(0.5,1) [6,4] id=2 2=(0,0.25) [5,1] 6=(0.25,0.5) [5,1,3] 4=(0.5,1) [5,3]
81id=1 1=(0,0.25) [6,2] 5=(0.25,0.5) [2,4,6] 3=(0.5,1) [8,6,4] id=2 2=(0,0.25) [5,1] 6=(0.25,0.5) [5,1,3] 4=(0.5,0.75) [5,3] 8=(0.75,1) [3]
82id=1 1=(0,0.25) [6,2] 5=(0.25,0.5) [2,4,6] 3=(0.5,0.75) [8,6,4] 7=(0.75,1) [4,8] id=2 2=(0,0.25) [5,1] 6=(0.25,0.5) [5,1,3] 4=(0.5,0.75) [7,5,3] 8=(0.75,1) [7,3]
83id=1 1=(0,0.25) [6,2] 5=(0.25,0.5) [2,4,6] 3=(0.5,0.75) [8,6,4] 7=(0.75,1) [10,4,8] id=2 2=(0,0.25) [5,1] 6=(0.25,0.5) [5,1,3] 4=(0.5,0.75) [7,5,3] 8=(0.75,0.875) [7,3] 10=(0.875,1) [7]
84id=1 1=(0,0.25) [6,2] 5=(0.25,0.5) [2,4,6] 3=(0.5,0.75) [8,6,4] 7=(0.75,0.875) [10,4,8] 9=(0.875,1) [8,10] id=2 2=(0,0.25) [5,1] 6=(0.25,0.5) [5,1,3] 4=(0.5,0.75) [7,5,3] 8=(0.75,0.875) [9,7,3] 10=(0.875,1) [9,7]
85id=1 1=(0,0.25) [12,6,2] 5=(0.25,0.5) [12,4,6] 3=(0.5,0.75) [8,6,4] 7=(0.75,0.875) [10,4,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [1] 12=(0.125,0.25) [1,5] 6=(0.25,0.5) [5,1,3] 4=(0.5,0.75) [7,5,3] 8=(0.75,0.875) [9,7,3] 10=(0.875,1) [9,7]
86id=1 1=(0,0.125) [12,2] 11=(0.125,0.25) [2,6,12] 5=(0.25,0.5) [12,4,6] 3=(0.5,0.75) [8,6,4] 7=(0.75,0.875) [10,4,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [11,1] 12=(0.125,0.25) [11,1,5] 6=(0.25,0.5) [11,5,3] 4=(0.5,0.75) [7,5,3] 8=(0.75,0.875) [9,7,3] 10=(0.875,1) [9,7]
87id=1 1=(0,0.125) [12,2] 11=(0.125,0.25) [2,6,12] 5=(0.25,0.5) [14,12,4,6] 3=(0.5,0.75) [14,8,4] 7=(0.75,0.875) [10,4,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [11,1] 12=(0.125,0.25) [11,1,5] 6=(0.25,0.375) [11,5] 14=(0.375,0.5) [3,5] 4=(0.5,0.75) [7,5,3] 8=(0.75,0.875) [9,7,3] 10=(0.875,1) [9,7]
88id=1 1=(0,0.125) [12,2] 11=(0.125,0.25) [2,6,12] 5=(0.25,0.375) [14,12,6] 13=(0.375,0.5) [6,4,14] 3=(0.5,0.75) [14,8,4] 7=(0.75,0.875) [10,4,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [11,1] 12=(0.125,0.25) [11,1,5] 6=(0.25,0.375) [13,11,5] 14=(0.375,0.5) [13,3,5] 4=(0.5,0.75) [13,7,3] 8=(0.75,0.875) [9,7,3] 10=(0.875,1) [9,7]
89id=1 1=(0,0.125) [12,2] 11=(0.125,0.25) [2,6,12] 5=(0.25,0.375) [14,12,6] 13=(0.375,0.5) [6,4,14] 3=(0.5,0.75) [16,14,8,4] 7=(0.75,0.875) [16,10,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [11,1] 12=(0.125,0.25) [11,1,5] 6=(0.25,0.375) [13,11,5] 14=(0.375,0.5) [13,3,5] 4=(0.5,0.625) [13,3] 16=(0.625,0.75) [3,7] 8=(0.75,0.875) [9,7,3] 10=(0.875,1) [9,7]
90id=1 1=(0,0.125) [12,2] 11=(0.125,0.25) [2,6,12] 5=(0.25,0.375) [14,12,6] 13=(0.375,0.5) [6,4,14] 3=(0.5,0.625) [16,14,4] 15=(0.625,0.75) [4,8,16] 7=(0.75,0.875) [16,10,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [11,1] 12=(0.125,0.25) [11,1,5] 6=(0.25,0.375) [13,11,5] 14=(0.375,0.5) [13,3,5] 4=(0.5,0.625) [15,13,3] 16=(0.625,0.75) [15,3,7] 8=(0.75,0.875) [15,9,7] 10=(0.875,1) [9,7]
91id=1 1=(0,0.125) [12,2] 11=(0.125,0.25) [18,2,6,12] 5=(0.25,0.375) [18,14,6] 13=(0.375,0.5) [6,4,14] 3=(0.5,0.625) [16,14,4] 15=(0.625,0.75) [4,8,16] 7=(0.75,0.875) [16,10,8] 9=(0.875,1) [8,10] id=2 2=(0,0.125) [11,1] 12=(0.125,0.1875) [11,1] 18=(0.1875,0.25) [5,11] 6=(0.25,0.375) [13,11,5] 14=(0.375,0.5) [13,3,5] 4=(0.5,0.625) [15,13,3] 16=(0.625,0.75) [15,3,7] 8=(0.75,0.875) [15,9,7] 10=(0.875,1) [9,7]
92setPerp t=0 cPt=(78,4565) == oppT=0 fPerpPt=(78,4565)
93setPerp t=0.125 cPt=(78.1001678,4563.90822) == oppT=0.125 fPerpPt=(78.1001678,4563.90822)
94setPerp t=0.1875 cPt=(78.2316063,4563.34905) == oppT=0.1875 fPerpPt=(78.2316063,4563.34905)
95setPerp t=0.25 cPt=(78.4212702,4562.79143) == oppT=0.25 fPerpPt=(78.4212702,4562.79143)
96setPerp t=0.375 cPt=(78.9780269,4561.71674) == oppT=0.375 fPerpPt=(78.9780269,4561.71674)
97setPerp t=0.5 cPt=(79.7573593,4560.75736) == oppT=0.5 fPerpPt=(79.7573593,4560.75736)
98setPerp t=0.625 cPt=(80.7167415,4559.97803) == oppT=0.625 fPerpPt=(80.7167415,4559.97803)
99setPerp t=0.75 cPt=(81.7914318,4559.42127) == oppT=0.75 fPerpPt=(81.7914318,4559.42127)
100setPerp t=0.875 cPt=(82.9082217,4559.10017) == oppT=0.875 fPerpPt=(82.9082217,4559.10017)
101setPerp t=1 cPt=(84,4559) == oppT=1 fPerpPt=(84,4559)
102setPerp t=0 cPt=(78,4565) == oppT=0 fPerpPt=(78,4565)
103setPerp t=1 cPt=(84,4559) == oppT=1 fPerpPt=(84,4559)
104id=1 (empty) id=2 (empty)
105debugShowConicIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wtTs[1]=1 {{84,4559}} wnTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} wnTs[1]=1
106debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {158,4559}}}
107debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {1170,4559}}}
108debugShowLineIntersection wtTs[0]=0 {{{84,4559}, {158,4559}}} {{84,4559}} wtTs[1]=1 {{158,4559}} wnTs[0]=0 {{{84,4559}, {1170,4559}}} wnTs[1]=0.0681399632
109SkOpSegment::addT insert t=0.0681399632 segID=8 spanID=34
110debugShowLineIntersection wtTs[0]=0 {{{158,4559}, {158,4596}}} {{158,4559}} wnTs[0]=0.06814 {{{84,4559}, {1170,4559}}}
111debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590}, {78,4565}}}
112debugShowConicLineIntersection wtTs[0]=1 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{78,4590}} wnTs[0]=0 {{{78,4590}, {78,4565}}}
113debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {158,4559}}}
114debugShowLineIntersection wtTs[0]=0 {{{158,4559}, {158,4596}}} {{158,4559}} wnTs[0]=1 {{{84,4559}, {158,4559}}}
115debugShowLineIntersection wtTs[0]=0 {{{158,4596}, {84,4596}}} {{158,4596}} wnTs[0]=1 {{{158,4559}, {158,4596}}}
116debugShowConicLineIntersection wtTs[0]=0 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{84,4596}} wnTs[0]=1 {{{158,4596}, {84,4596}}}
117------------x-------- start
118------------x-------- moveMultiples
119------------x-------- findCollapsed
120------------x-------- moveNearby
121------------x-------- align
122------------x-------- fixAligned
123------------x-------- addAlignIntersections
124------------x-------- expand2
125------------x-------- mark1
126------------x-------- missingCoincidence1
127------------x-------- expand3
128------------x-------- addExpanded2
129------------x-------- missingCoincidence2
130SkOpSegment::markDone id=8 (84,4559 1170,4559) t=0 [15] (84,4559) tEnd=0.0681399632 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
131SkOpSegment::markDone id=10 (78,4565 78,4559 84,4559) t=0 [19] (78,4565) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
132SkOpSegment::markDone id=6 (78,4590.00586 78,4565) t=0.000234320081 [33] (78,4590) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
133------------x-------- pairs->apply
134------------x-------- pairs->findOverlaps
135SkOpSegment::sortAngles [4] tStart=0.931066176 [29]
136SkOpAngle::after [4/1] 31/31 tStart=0.931066176 tEnd=0 < [12/14] 7/7 tStart=0.972972973 tEnd=0 < [4/2] 15/15 tStart=0.931066176 tEnd=1 T 4
137SkOpAngle::afterPart {{{158,4595}, {1171,4595}}} id=4
138SkOpAngle::afterPart {{{158,4595}, {158,4559}}} id=12
139SkOpAngle::afterPart {{{158,4595}, {83,4595}}} id=4
140SkOpAngle::after [4/1] 31/31 tStart=0.931066176 tEnd=0 < [12/15] 23/23 tStart=0.972972973 tEnd=1 < [12/14] 7/7 tStart=0.972972973 tEnd=0 F 4
141SkOpAngle::afterPart {{{158,4595}, {1171,4595}}} id=4
142SkOpAngle::afterPart {{{158,4595}, {158,4596}}} id=12
143SkOpAngle::afterPart {{{158,4595}, {158,4559}}} id=12
144SkOpAngle::after [12/14] 7/7 tStart=0.972972973 tEnd=0 < [12/15] 23/23 tStart=0.972972973 tEnd=1 < [4/2] 15/15 tStart=0.931066176 tEnd=1 F 4
145SkOpAngle::afterPart {{{158,4595}, {158,4559}}} id=12
146SkOpAngle::afterPart {{{158,4595}, {158,4596}}} id=12
147SkOpAngle::afterPart {{{158,4595}, {83,4595}}} id=4
148SkOpAngle::after [4/2] 15/15 tStart=0.931066176 tEnd=1 < [12/15] 23/23 tStart=0.972972973 tEnd=1 < [4/1] 31/31 tStart=0.931066176 tEnd=0 T 4
149SkOpAngle::afterPart {{{158,4595}, {83,4595}}} id=4
150SkOpAngle::afterPart {{{158,4595}, {158,4596}}} id=12
151SkOpAngle::afterPart {{{158,4595}, {1171,4595}}} id=4
152SkOpSegment::sortAngles [5] tStart=0.999339899 [31]
153SkOpAngle::after [5/3] 25/29 tStart=0.999339899 tEnd=0 < [14/16] 25/29 tStart=0.998759893 tEnd=0 < [5/4] 9/9 tStart=0.999339899 tEnd=1 F 12
154SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0133288,4595}, {83,4595}}}, 0.877537966} id=5
155SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0105173,4596}, {84,4596}}}, 0.877548993} id=14
156SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0000041,4590.00819}, {78,4590.00586}}}, 0.999999881} id=5
157SkOpAngle::after [5/3] 25/29 tStart=0.999339899 tEnd=0 < [14/17] 9/9 tStart=0.998759893 tEnd=1 < [5/4] 9/9 tStart=0.999339899 tEnd=1 T 11
158SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0133288,4595}, {83,4595}}}, 0.877537966} id=5
159SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78,4590.00526}, {78,4590}}}, 0.999999642} id=14
160SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0000041,4590.00819}, {78,4590.00586}}}, 0.999999881} id=5
161SkOpSegment::sortAngles [6] tStart=0.000234320081 [33]
162SkOpAngle::after [6/5] 23/23 tStart=0.000234320081 tEnd=0 < [9/9] 7/7 tStart=0 tEnd=1 < [14/18] 21/21 tStart=1 tEnd=0.998759893 T 4
163SkOpAngle::afterPart {{{78,4590}, {78,4590.00586}}} id=6
164SkOpAngle::afterPart {{{78,4590}, {78,4565}}} id=9
165SkOpAngle::afterPart {{{{78,4590}, {78,4590.00526}, {78.0000076,4590.01074}}}, 0.999999642} id=14
166SkOpSegment::sortAngles [7] tStart=0 [13]
167SkOpSegment::sortAngles [7] tStart=1 [14]
168SkOpSegment::sortAngles [8] tStart=0.0681399632 [34]
169SkOpAngle::after [8/8] 31/31 tStart=0.0681399632 tEnd=1 < [11/12] 15/15 tStart=1 tEnd=0 < [12/13] 23/23 tStart=0 tEnd=0.972972973 T 4
170SkOpAngle::afterPart {{{158,4559}, {1170,4559}}} id=8
171SkOpAngle::afterPart {{{158,4559}, {84,4559}}} id=11
172SkOpAngle::afterPart {{{158,4559}, {158,4595}}} id=12
caryclark27c8eb82015-07-06 11:38:33 -0700173SkOpSegment::sortAngles [9] tStart=0 [17]
caryclark26ad22a2015-10-16 09:03:38 -0700174SkOpSegment::sortAngles [9] tStart=1 [18]
175SkOpSegment::sortAngles [11] tStart=0 [21]
176SkOpSegment::sortAngles [11] tStart=1 [22]
177SkOpSegment::sortAngles [12] tStart=0 [23]
178SkOpSegment::sortAngles [12] tStart=0.972972973 [30]
179SkOpSegment::sortAngles [14] tStart=0.998759893 [32]
180SkOpSegment::sortAngles [14] tStart=1 [28]
181SkOpCoincidence::debugShowCoincidence - id=11 t=0 tEnd=1
182SkOpCoincidence::debugShowCoincidence + id=8 t=0 tEnd=0.0681399632
183SkOpCoincidence::debugShowCoincidence - id=7 t=0 tEnd=1
184SkOpCoincidence::debugShowCoincidence + id=10 t=0 tEnd=1
185SkOpCoincidence::debugShowCoincidence - id=9 t=0 tEnd=1
186SkOpCoincidence::debugShowCoincidence + id=6 t=0.000234320081 tEnd=1
187SkOpSegment::debugShowActiveSpans id=1 (1170,4559 1176,4559 1176,4565 0.707106769f) t=0 (1170,4559) tEnd=1 windSum=? windValue=1
188SkOpSegment::debugShowActiveSpans id=2 (1176,4565 1176,4590) t=0 (1176,4565) tEnd=1 windSum=? windValue=1
189SkOpSegment::debugShowActiveSpans id=3 (1176,4590 1176,4595 1171,4595 0.707106769f) t=0 (1176,4590) tEnd=1 windSum=? windValue=1
190SkOpSegment::debugShowActiveSpans id=4 (1171,4595 83,4595) t=0 (1171,4595) tEnd=0.931066176 windSum=? windValue=1
191SkOpSegment::debugShowActiveSpans id=4 (1171,4595 83,4595) t=0.931066176 (158,4595) tEnd=1 windSum=? windValue=1
192SkOpSegment::debugShowActiveSpans id=5 (83,4595 78.0086746,4595 78,4590.00586 0.707720578f) t=0 (83,4595) tEnd=0.999339899 windSum=? windValue=1
193SkOpSegment::debugShowActiveSpans id=5 (83,4595 78.0086746,4595 78,4590.00586 0.707720578f) t=0.999339899 (78.0000076,4590.01074) tEnd=1 windSum=? windValue=1
194SkOpSegment::debugShowActiveSpans id=6 (78,4590.00586 78,4565) t=0 (78,4590.00586) tEnd=0.000234320081 windSum=? windValue=1
195SkOpSegment::debugShowActiveSpans id=7 (78,4565 78,4559 84,4559 0.707106769f) t=0 (78,4565) tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
196SkOpSegment::debugShowActiveSpans id=8 (84,4559 1170,4559) t=0.0681399632 (158,4559) tEnd=1 windSum=? windValue=1
197SkOpSegment::debugShowActiveSpans id=9 (78,4590 78,4565) t=0 (78,4590) tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
198SkOpSegment::debugShowActiveSpans id=11 (84,4559 158,4559) t=0 (84,4559) tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
199SkOpSegment::debugShowActiveSpans id=12 (158,4559 158,4596) t=0 (158,4559) tEnd=0.972972973 windSum=? windValue=1
200SkOpSegment::debugShowActiveSpans id=12 (158,4559 158,4596) t=0.972972973 (158,4595) tEnd=1 windSum=? windValue=1
201SkOpSegment::debugShowActiveSpans id=13 (158,4596 84,4596) t=0 (158,4596) tEnd=1 windSum=? windValue=1
202SkOpSegment::debugShowActiveSpans id=14 (84,4596 78,4596 78,4590 0.707106769f) t=0 (84,4596) tEnd=0.998759893 windSum=? windValue=1
203SkOpSegment::debugShowActiveSpans id=14 (84,4596 78,4596 78,4590 0.707106769f) t=0.998759893 (78.0000076,4590.01074) tEnd=1 windSum=? windValue=1
204SkOpSpan::sortableTop dir=kTop seg=1 t=0.5 pt=(1174.24268,4560.75732)
205SkOpSpan::sortableTop [0] valid=1 operand=0 span=1 ccw=1 seg=1 {{{{1170, 4559}, {1176, 4559}, {1176, 4565}}}, 0.707106769f} t=0.5 pt=(1174.24268,4560.75732) slope=(2.56066015,2.56066015)
206SkOpSegment::markWinding id=1 (1170,4559 1176,4559 1176,4565) t=0 [1] (1170,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
207SkOpSegment::markWinding id=2 (1176,4565 1176,4590) t=0 [3] (1176,4565) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
208SkOpSegment::markWinding id=3 (1176,4590 1176,4595 1171,4595) t=0 [5] (1176,4590) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
209SkOpSegment::markWinding id=4 (1171,4595 83,4595) t=0 [7] (1171,4595) tEnd=0.931066176 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
210SkOpSegment::markWinding id=1 (1170,4559 1176,4559 1176,4565) t=0 [1] (1170,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
211SkOpSegment::markWinding id=8 (84,4559 1170,4559) t=0.0681399632 [34] (158,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
caryclark27c8eb82015-07-06 11:38:33 -0700212SkOpSegment::activeOp id=1 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
213SkOpSegment::findNextOp simple
caryclark26ad22a2015-10-16 09:03:38 -0700214SkOpSegment::markDone id=1 (1170,4559 1176,4559 1176,4565) t=0 [1] (1170,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
215bridgeOp current id=1 from=(1176,4565) to=(1170,4559)
216path.moveTo(1176,4565);
217path.conicTo(1176,4559, 1170,4559, 0.707106769);
218SkOpSegment::markWinding id=11 (84,4559 158,4559) t=0 [21] (84,4559) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
219SkOpSegment::markWinding id=7 (78,4565 78,4559 84,4559) t=0 [13] (78,4565) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
220SkOpSegment::markWinding id=9 (78,4590 78,4565) t=0 [17] (78,4590) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
221SkOpSegment::markAngle last segment=9 span=17 windSum=-1
222SkOpSegment::markWinding id=12 (158,4559 158,4596) t=0 [23] (158,4559) tEnd=0.972972973 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
223SkOpSegment::markAngle last segment=12 span=30 windSum=?
caryclark27c8eb82015-07-06 11:38:33 -0700224SkOpSegment::findNextOp
caryclark26ad22a2015-10-16 09:03:38 -0700225SkOpAngle::dumpOne [8/8] next=11/12 sect=31/31 s=0.0681399632 [34] e=1 [16] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
226SkOpAngle::dumpOne [11/12] next=12/13 sect=15/15 s=1 [22] e=0 [21] sgn=1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 operand
227SkOpAngle::dumpOne [12/13] next=8/8 sect=23/23 s=0 [23] e=0.972972973 [30] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 operand
228SkOpSegment::activeOp id=11 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=1 result=1
229SkOpSegment::findNextOp chase.append segment=9 span=17 windSum=-1
230SkOpSegment::activeOp id=12 t=0 tEnd=0.972972973 op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
231SkOpSegment::markDone id=12 (158,4559 158,4596) t=0 [23] (158,4559) tEnd=0.972972973 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
232SkOpSegment::findNextOp chase.append segment=12 span=30 windSum=-2147483647
233SkOpSegment::markDone id=8 (84,4559 1170,4559) t=0.0681399632 [34] (158,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
234SkOpSegment::findNextOp from:[8] to:[11] start=8985900 end=8985796
235bridgeOp current id=8 from=(1170,4559) to=(158,4559)
caryclark27c8eb82015-07-06 11:38:33 -0700236SkOpSegment::findNextOp simple
caryclark26ad22a2015-10-16 09:03:38 -0700237SkOpSegment::markDone id=11 (84,4559 158,4559) t=0 [21] (84,4559) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
238bridgeOp current id=11 from=(158,4559) to=(84,4559)
239SkOpSegment::findNextOp simple
240SkOpSegment::markDone id=7 (78,4565 78,4559 84,4559) t=0 [13] (78,4565) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
241bridgeOp current id=7 from=(84,4559) to=(78,4565)
242path.lineTo(84,4559);
243path.conicTo(78,4559, 78,4565, 0.707106769);
244SkOpSegment::markWinding id=14 (84,4596 78,4596 78,4590) t=0.998759893 [32] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
245SkOpSegment::markAngle last segment=14 span=32 windSum=-1
246SkOpSegment::markWinding id=6 (78,4590.00586 78,4565) t=0 [11] (78,4590.00586) tEnd=0.000234320081 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
247SkOpSegment::markWinding id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0.999339899 [31] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
248SkOpSegment::markAngle last segment=5 span=31 windSum=-1
caryclark27c8eb82015-07-06 11:38:33 -0700249SkOpSegment::findNextOp
caryclark26ad22a2015-10-16 09:03:38 -0700250SkOpAngle::dumpOne [9/9] next=14/18 sect=7/7 s=0 [17] e=1 [18] sgn=-1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 operand
251SkOpAngle::dumpOne [14/18] next=6/5 sect=21/21 s=1 [28] e=0.998759893 [32] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
252SkOpAngle::dumpOne [6/5] next=9/9 sect=23/23 s=0.000234320081 [33] e=0 [11] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1
253SkOpSegment::activeOp id=14 t=1 tEnd=0.998759893 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
254SkOpSegment::findNextOp chase.append segment=14 span=32 windSum=-1
255SkOpSegment::activeOp id=6 t=0.000234320081 tEnd=0 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
256SkOpSegment::markDone id=6 (78,4590.00586 78,4565) t=0 [11] (78,4590.00586) tEnd=0.000234320081 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
257SkOpSegment::markDone id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0.999339899 [31] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
258SkOpSegment::findNextOp chase.append segment=5 span=31 windSum=-1
259SkOpSegment::markDone id=9 (78,4590 78,4565) t=0 [17] (78,4590) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
260SkOpSegment::findNextOp from:[9] to:[14] start=8986620 end=8987068
261bridgeOp current id=9 from=(78,4565) to=(78,4590)
262SkOpSegment::markWinding id=14 (84,4596 78,4596 78,4590) t=0 [27] (84,4596) tEnd=0.998759893 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
263SkOpSegment::markWinding id=13 (158,4596 84,4596) t=0 [25] (158,4596) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
264SkOpSegment::markWinding id=12 (158,4559 158,4596) t=0.972972973 [30] (158,4595) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
265SkOpSegment::markAngle last segment=12 span=30 windSum=-2
266SkOpSegment::markWinding id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0 [9] (83,4595) tEnd=0.999339899 newWindSum=-1 newOppSum=-2 oppSum=? windSum=? windValue=1 oppValue=0
267SkOpSegment::markWinding id=4 (1171,4595 83,4595) t=0.931066176 [29] (158,4595) tEnd=1 newWindSum=-1 newOppSum=-2 oppSum=? windSum=? windValue=1 oppValue=0
268SkOpSegment::markAngle last segment=4 span=29 windSum=-1
caryclark27c8eb82015-07-06 11:38:33 -0700269SkOpSegment::findNextOp
caryclark26ad22a2015-10-16 09:03:38 -0700270SkOpAngle::dumpOne [14/17] next=5/4 sect=9/9 s=0.998759893 [32] e=1 [28] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
271SkOpAngle::dumpOne [5/4] next=14/16 sect=9/9 s=0.999339899 [31] e=1 [10] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 done
272SkOpAngle::dumpOne [14/16] next=5/3 sect=25/29 s=0.998759893 [32] e=0 [27] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=0 operand
273SkOpAngle::dumpOne [5/3] next=14/17 sect=25/29 s=0.999339899 [31] e=0 [9] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-2
274SkOpSegment::activeOp id=5 t=0.999339899 tEnd=1 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
275SkOpSegment::activeOp id=14 t=0.998759893 tEnd=0 op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
276SkOpSegment::markDone id=14 (84,4596 78,4596 78,4590) t=0 [27] (84,4596) tEnd=0.998759893 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
277SkOpSegment::markDone id=13 (158,4596 84,4596) t=0 [25] (158,4596) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
278SkOpSegment::markDone id=12 (158,4559 158,4596) t=0.972972973 [30] (158,4595) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
279SkOpSegment::activeOp id=5 t=0.999339899 tEnd=0 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
280SkOpSegment::markDone id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0 [9] (83,4595) tEnd=0.999339899 newWindSum=-1 newOppSum=-2 oppSum=-2 windSum=-1 windValue=1 oppValue=0
281SkOpSegment::markDone id=4 (1171,4595 83,4595) t=0.931066176 [29] (158,4595) tEnd=1 newWindSum=-1 newOppSum=-2 oppSum=-2 windSum=-1 windValue=1 oppValue=0
282SkOpSegment::findNextOp chase.append segment=4 span=29 windSum=-1
283SkOpSegment::markDone id=14 (84,4596 78,4596 78,4590) t=0.998759893 [32] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
284SkOpSegment::findNextOp from:[14] to:[5] start=8986964 end=8984396
285bridgeOp current id=14 from=(78,4590) to=(78.0000076,4590.01074)
286path.lineTo(78,4590);
287path.conicTo(78,4590.00537, 78.0000076,4590.01074, 0.999999642);
288SkOpSegment::debugShowActiveSpans id=2 (1176,4565 1176,4590) t=0 (1176,4565) tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
289SkOpSegment::debugShowActiveSpans id=3 (1176,4590 1176,4595 1171,4595 0.707106769f) t=0 (1176,4590) tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
290SkOpSegment::debugShowActiveSpans id=4 (1171,4595 83,4595) t=0 (1171,4595) tEnd=0.931066176 windSum=-1 oppSum=0 windValue=1 oppValue=0
291SkOpSegment::activeOp id=4 t=0.931066176 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
292SkOpSegment::findNextOp simple
293SkOpSegment::markDone id=4 (1171,4595 83,4595) t=0 [7] (1171,4595) tEnd=0.931066176 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
294bridgeOp current id=4 from=(158,4595) to=(1171,4595)
295SkOpSegment::findNextOp simple
296SkOpSegment::markDone id=3 (1176,4590 1176,4595 1171,4595) t=0 [5] (1176,4590) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
297bridgeOp current id=3 from=(1171,4595) to=(1176,4590)
298path.moveTo(158,4595);
299path.lineTo(1171,4595);
300path.conicTo(1176,4595, 1176,4590, 0.707106769);
301SkOpSegment::findNextOp simple
302SkOpSegment::markDone id=2 (1176,4565 1176,4590) t=0 [3] (1176,4565) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
303bridgeOp current id=2 from=(1176,4590) to=(1176,4565)
304path.lineTo(1176,4565);
caryclarkdac1d172014-06-17 05:15:38 -0700305</div>
caryclark26ad22a2015-10-16 09:03:38 -0700306
caryclarkdac1d172014-06-17 05:15:38 -0700307</div>
308
309<script type="text/javascript">
310
311var testDivs = [
caryclark26ad22a2015-10-16 09:03:38 -0700312 skpwww_gorcraft_ru_1,
caryclarkdac1d172014-06-17 05:15:38 -0700313];
314
315var decimal_places = 3; // make this 3 to show more precision
316
317var tests = [];
318var testLines = [];
319var testTitles = [];
320var testIndex = 0;
321var ctx;
322
323var xmin, xmax, focusXmin, focusXmax;
324var ymin, ymax, focusYmin, focusYmax;
325var scale;
326var mouseX, mouseY;
327var srcLeft, srcTop;
328var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700329var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700330var curveT = 0;
331
332var pt_labels = 2;
333var collect_bounds = false;
334var control_lines = 0;
335var curve_t = false;
336var debug_xy = 1;
337var focus_enabled = false;
338var focus_on_selection = false;
339var step_limit = 0;
340var draw_active = false;
341var draw_add = false;
342var draw_angle = 0;
caryclark624637c2015-05-11 07:21:27 -0700343var draw_coincidence = false;
caryclarkdac1d172014-06-17 05:15:38 -0700344var draw_deriviatives = 0;
345var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700346var draw_id = false;
347var draw_intersection = 0;
348var draw_intersectT = false;
349var draw_legend = true;
350var draw_log = false;
351var draw_mark = false;
352var draw_midpoint = false;
353var draw_op = 0;
354var draw_sequence = false;
355var draw_sort = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700356var draw_top = false;
caryclarkdac1d172014-06-17 05:15:38 -0700357var draw_path = 3;
358var draw_computed = 0;
359var retina_scale = !!window.devicePixelRatio;
360
361var activeCount = 0;
362var addCount = 0;
363var angleCount = 0;
caryclark624637c2015-05-11 07:21:27 -0700364var coinCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700365var opCount = 0;
366var sectCount = 0;
367var sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700368var topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700369var markCount = 0;
370var activeMax = 0;
371var addMax = 0;
372var angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -0700373var coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700374var sectMax = 0;
375var sectMax2 = 0;
376var sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700377var topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700378var markMax = 0;
379var opMax = 0;
380var stepMax = 0;
381var lastIndex = 0;
382var hasPath = false;
caryclark26ad22a2015-10-16 09:03:38 -0700383var hasAlignedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -0700384var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700385var angleBetween = false;
386var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700387
388var firstActiveSpan = -1;
389var logStart = -1;
390var logRange = 0;
391
392var SPAN_ID = 0;
393var SPAN_X1 = SPAN_ID + 1;
394var SPAN_Y1 = SPAN_X1 + 1;
395var SPAN_X2 = SPAN_Y1 + 1;
396var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700397
caryclarkdac1d172014-06-17 05:15:38 -0700398var SPAN_L_T = SPAN_Y2 + 1;
399var SPAN_L_TX = SPAN_L_T + 1;
400var SPAN_L_TY = SPAN_L_TX + 1;
401var SPAN_L_TEND = SPAN_L_TY + 1;
402var SPAN_L_OTHER = SPAN_L_TEND + 1;
403var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
404var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
405var SPAN_L_SUM = SPAN_L_OTHERI + 1;
406var SPAN_L_VAL = SPAN_L_SUM + 1;
407var SPAN_L_OPP = SPAN_L_VAL + 1;
408
409var SPAN_X3 = SPAN_Y2 + 1;
410var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700411
caryclarkdac1d172014-06-17 05:15:38 -0700412var SPAN_Q_T = SPAN_Y3 + 1;
413var SPAN_Q_TX = SPAN_Q_T + 1;
414var SPAN_Q_TY = SPAN_Q_TX + 1;
415var SPAN_Q_TEND = SPAN_Q_TY + 1;
416var SPAN_Q_OTHER = SPAN_Q_TEND + 1;
417var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
418var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
419var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
420var SPAN_Q_VAL = SPAN_Q_SUM + 1;
421var SPAN_Q_OPP = SPAN_Q_VAL + 1;
422
caryclark1049f122015-04-20 08:31:59 -0700423var SPAN_K_W = SPAN_Y3 + 1;
424var SPAN_K_T = SPAN_K_W + 1;
425var SPAN_K_TX = SPAN_K_T + 1;
426var SPAN_K_TY = SPAN_K_TX + 1;
427var SPAN_K_TEND = SPAN_K_TY + 1;
428var SPAN_K_OTHER = SPAN_K_TEND + 1;
429var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
430var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
431var SPAN_K_SUM = SPAN_K_OTHERI + 1;
432var SPAN_K_VAL = SPAN_K_SUM + 1;
433var SPAN_K_OPP = SPAN_K_VAL + 1;
434
caryclarkdac1d172014-06-17 05:15:38 -0700435var SPAN_X4 = SPAN_Y3 + 1;
436var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700437
caryclarkdac1d172014-06-17 05:15:38 -0700438var SPAN_C_T = SPAN_Y4 + 1;
439var SPAN_C_TX = SPAN_C_T + 1;
440var SPAN_C_TY = SPAN_C_TX + 1;
441var SPAN_C_TEND = SPAN_C_TY + 1;
442var SPAN_C_OTHER = SPAN_C_TEND + 1;
443var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
444var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
445var SPAN_C_SUM = SPAN_C_OTHERI + 1;
446var SPAN_C_VAL = SPAN_C_SUM + 1;
447var SPAN_C_OPP = SPAN_C_VAL + 1;
448
449var ACTIVE_LINE_SPAN = 1;
450var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700451var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
452var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700453
454var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
455var ADD_LINETO = ADD_MOVETO + 1;
456var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700457var ADD_CONICTO = ADD_QUADTO + 1;
458var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700459var ADD_CLOSE = ADD_CUBICTO + 1;
460var ADD_FILL = ADD_CLOSE + 1;
461
462var PATH_LINE = ADD_FILL + 1;
463var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700464var PATH_CONIC = PATH_QUAD + 1;
465var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700466
467var INTERSECT_LINE = PATH_CUBIC + 1;
468var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
469var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
470var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
471var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
472var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
473var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
474var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
475var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700476var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
477var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
478var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
479var INTERSECT_CONIC = INTERSECT_CONIC_LINE_NO + 1;
480var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
481var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
482var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700483var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
484var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
485var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
486var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
487var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
488var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
489var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
490var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
491var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
492var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
493var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
494var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
495var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
496var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
497// FIXME: add cubic 5- 9
498var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
499
500var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
501var SORT_BINARY = SORT_UNARY + 1;
502
503var OP_DIFFERENCE = SORT_BINARY + 1;
504var OP_INTERSECT = OP_DIFFERENCE + 1;
505var OP_UNION = OP_INTERSECT + 1;
506var OP_XOR = OP_UNION + 1;
507
508var MARK_LINE = OP_XOR + 1;
509var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700510var MARK_CONIC = MARK_QUAD + 1;
511var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700512var MARK_DONE_LINE = MARK_CUBIC + 1;
513var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700514var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
515var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700516var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
517var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700518var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
519var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700520var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
521var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700522var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
523var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700524var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
525var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700526var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
527var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700528var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
529var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700530var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
531var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700532var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
533
534var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
535var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
536
caryclark624637c2015-05-11 07:21:27 -0700537var ANGLE_AFTER = COMPUTED_SET_2 + 1;
caryclark54359292015-03-26 07:52:43 -0700538var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700539
caryclark54359292015-03-26 07:52:43 -0700540var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700541
caryclark624637c2015-05-11 07:21:27 -0700542var COIN_MAIN_SPAN = ACTIVE_OP + 1;
543var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1;
544
545var FRAG_TYPE_LAST = COIN_OPP_SPAN;
caryclarkdac1d172014-06-17 05:15:38 -0700546
547var REC_TYPE_UNKNOWN = -1;
548var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700549var REC_TYPE_PATH2 = 1;
550var REC_TYPE_SECT = 2;
551var REC_TYPE_ACTIVE = 3;
552var REC_TYPE_ADD = 4;
553var REC_TYPE_SORT = 5;
554var REC_TYPE_OP = 6;
555var REC_TYPE_MARK = 7;
556var REC_TYPE_COMPUTED = 8;
557var REC_TYPE_COIN = 9;
558var REC_TYPE_ANGLE = 10;
559var REC_TYPE_ACTIVE_OP = 11;
560var REC_TYPE_AFTERPART = 12;
caryclark03b03ca2015-04-23 09:13:37 -0700561var REC_TYPE_TOP = 13;
caryclark624637c2015-05-11 07:21:27 -0700562var REC_TYPE_COINCIDENCE = 14;
caryclark26ad22a2015-10-16 09:03:38 -0700563var REC_TYPE_ALIGNED = 15;
564var REC_TYPE_LAST = REC_TYPE_ALIGNED;
caryclarkdac1d172014-06-17 05:15:38 -0700565
566function strs_to_nums(strs) {
567 var result = [];
568 for (var idx = 1; idx < strs.length; ++idx) {
569 var str = strs[idx];
570 var num = parseFloat(str);
571 if (isNaN(num)) {
572 result.push(str);
573 } else {
574 result.push(num);
575 }
576 }
577 return result;
578}
579
580function filter_str_by(id, str, regex, array) {
581 if (regex.test(str)) {
582 var strs = regex.exec(str);
583 var result = strs_to_nums(strs);
584 array.push(id);
585 array.push(result);
586 return true;
587 }
588 return false;
589}
590
591function construct_regexp2(pattern) {
592 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
593 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
594 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700595 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700596 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
597 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
598 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700599 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700600 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
601 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
602 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700603 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700604 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700605 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700606 escape = escape.replace(/NUM/g, "(-?\\d+)");
607 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
608 return new RegExp(escape, 'i');
609}
610
611function construct_regexp2c(pattern) {
612 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
613 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700614 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700615 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700616 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
617 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700618 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700619 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700620 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
caryclark54359292015-03-26 07:52:43 -0700621 escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700622 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700623 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700624 escape = escape.replace(/OPER/g, "[a-z]+");
625 escape = escape.replace(/PATH/g, "pathB?");
626 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700627 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700628 escape = escape.replace(/NUM/g, "(-?\\d+)");
629 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
630 return new RegExp(escape, 'i');
631}
632
633function match_regexp(str, lineNo, array, id, pattern) {
634 var regex = construct_regexp2(pattern);
635 if (filter_str_by(id, str, regex, array)) {
636 return true;
637 }
638 regex = construct_regexp2c(pattern);
639 return filter_str_by(id, str, regex, array);
640}
641
642function endsWith(str, suffix) {
643 return str.indexOf(suffix, str.length - suffix.length) !== -1;
644}
645
646function parse_all(test) {
647 var lines = test.match(/[^\r\n]+/g);
648 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
649 var record = [];
650 var recType = REC_TYPE_UNKNOWN;
651 var lastLineNo;
652 var moveX, moveY;
653 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
654 var line = lines[lineNo];
655 if (line.length == 0) {
656 continue;
657 }
658 var opStart = "SkOpSegment::";
659 if (line.lastIndexOf(opStart, 0) === 0) {
660 line = line.substr(opStart.length);
661 }
662 var angleStart = "SkOpAngle::";
663 if (line.lastIndexOf(angleStart, 0) === 0) {
664 line = line.substr(angleStart.length);
665 }
caryclark624637c2015-05-11 07:21:27 -0700666 var coinStart = "SkOpCoincidence::";
667 if (line.lastIndexOf(coinStart, 0) === 0) {
668 line = line.substr(coinStart.length);
669 }
caryclark54359292015-03-26 07:52:43 -0700670 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
caryclark624637c2015-05-11 07:21:27 -0700671 : line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE
caryclark54359292015-03-26 07:52:43 -0700672 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclarkdac1d172014-06-17 05:15:38 -0700673 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
caryclark54359292015-03-26 07:52:43 -0700674 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700675 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
676 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
677 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
678 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
caryclark26ad22a2015-10-16 09:03:38 -0700679 : line.lastIndexOf("aligned=", 0) === 0 ? REC_TYPE_ALIGNED
caryclarkdac1d172014-06-17 05:15:38 -0700680 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
caryclark03b03ca2015-04-23 09:13:37 -0700681 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
caryclarkdac1d172014-06-17 05:15:38 -0700682 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
683 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
684 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
685 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
686 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700687 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700688 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
689 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
690 : REC_TYPE_UNKNOWN;
691 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
692 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
693 if (recType != REC_TYPE_UNKNOWN) {
694 records.push(recType);
695 records.push(lastLineNo);
696 records.push(record);
697 }
698 record = [];
699 recType = type;
700 lastLineNo = lineNo;
701 }
702 var found = false;
703 switch (recType) {
704 case REC_TYPE_ACTIVE:
705 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700706" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700707 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700708" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700709 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700710" id=IDX CONIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700711 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700712" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
713 ) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
714" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
715 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
716" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
717 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
718" id=IDX CONIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
719 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
720" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700721 );
722 break;
723 case REC_TYPE_ACTIVE_OP:
724 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
725" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
726 );
727 break;
728 case REC_TYPE_ADD:
729 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
730 moveX = record[1][0];
731 moveY = record[1][1];
732 found = true;
733 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
734 record[1].unshift(moveY);
735 record[1].unshift(moveX);
736 moveX = record[1][2];
737 moveY = record[1][3];
738 found = true;
739 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
740 record[1].unshift(moveY);
741 record[1].unshift(moveX);
742 moveX = record[1][4];
743 moveY = record[1][5];
744 found = true;
caryclark1049f122015-04-20 08:31:59 -0700745 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
746 record[1].unshift(moveY);
747 record[1].unshift(moveX);
748 moveX = record[1][4];
749 moveY = record[1][5];
750 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700751 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
752 record[1].unshift(moveY);
753 record[1].unshift(moveX);
754 moveX = record[1][6];
755 moveY = record[1][7];
756 found = true;
757 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
758 found = true;
759 } else {
760 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
761 }
762 break;
caryclark54359292015-03-26 07:52:43 -0700763 case REC_TYPE_AFTERPART:
764 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL")
765 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL")
caryclark1049f122015-04-20 08:31:59 -0700766 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL")
caryclark54359292015-03-26 07:52:43 -0700767 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL")
768 break;
caryclark26ad22a2015-10-16 09:03:38 -0700769 case REC_TYPE_ALIGNED:
770 found = match_regexp(line, lineNo, record, PATH_LINE, "aligned=IDX LINE_VAL"
771 ) || match_regexp(line, lineNo, record, PATH_QUAD, "aligned=IDX QUAD_VAL"
772 ) || match_regexp(line, lineNo, record, PATH_CONIC, "aligned=IDX CONIC_VAL"
773 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "aligned=IDX CUBIC_VAL"
774 );
775 break;
caryclarkdac1d172014-06-17 05:15:38 -0700776 case REC_TYPE_ANGLE:
777 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
caryclarkdac1d172014-06-17 05:15:38 -0700778"[IDX/IDX] NUM/NUM tStart=T_VAL tEnd=T_VAL < [IDX/IDX] NUM/NUM tStart=T_VAL tEnd=T_VAL < [IDX/IDX] NUM/NUM tStart=T_VAL tEnd=T_VAL T_F IDX");
779 break;
780 case REC_TYPE_COIN:
781 found = true;
782 break;
caryclark624637c2015-05-11 07:21:27 -0700783 case REC_TYPE_COINCIDENCE:
784 found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" +
785" + id=IDX t=T_VAL tEnd=T_VAL"
786 ) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" +
787" - id=IDX t=T_VAL tEnd=T_VAL"
788 );
789 break;
caryclarkdac1d172014-06-17 05:15:38 -0700790 case REC_TYPE_COMPUTED:
791 found = line == "computed quadratics given"
792 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
793 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
794 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -0700795 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -0700796 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
797 );
798 break;
799 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700800 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
801 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700802 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -0700803 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
804 );
805 break;
806 case REC_TYPE_PATH2:
807 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
808 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -0700809 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -0700810 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -0700811 );
812 break;
813 case REC_TYPE_SECT:
814 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
815" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
816 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
817" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
818 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
819" no intersect LINE_VAL LINE_VAL"
820 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
821" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
822 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
823" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
824 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
825" no intersect QUAD_VAL LINE_VAL"
826 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
827" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
828 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
829" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
830 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
831" no intersect QUAD_VAL QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700832 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
833" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
834 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
835" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
836 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
837" no intersect CONIC_VAL LINE_VAL"
838 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
839" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
840 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
841" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
842 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
843" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -0700844 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
845" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
846 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
847" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
848 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
849" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL"
850 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
851" no intersect CUBIC_VAL LINE_VAL"
852 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
853" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
854 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
855" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
856 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
857" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL"
858 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
859" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL wtTs[3]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL"
860 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
861" no intersect CUBIC_VAL QUAD_VAL"
862 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
863" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
864 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
865" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
866 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
867" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL"
868 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
869" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wtTs[3]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL"
870 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
871" no intersect CUBIC_VAL CUBIC_VAL"
872 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
873" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
874 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
875" no self intersect CUBIC_VAL"
876 );
877 break;
878 case REC_TYPE_SORT:
879 var hasDone = / done/.test(line);
880 var hasUnorderable = / unorderable/.test(line);
881 var hasSmall = / small/.test(line);
882 var hasTiny = / tiny/.test(line);
883 var hasOperand = / operand/.test(line);
884 var hasStop = / stop/.test(line);
885 line.replace(/[ a-z]+$/, "");
886 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
887" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
888 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
889" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT oppVal=IDX oppSum=OPT"
890 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
891" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
892 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
893" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT oppVal=IDX oppSum=OPT"
894 );
895 if (found) {
896 record[1].push(hasDone);
897 record[1].push(hasUnorderable);
898 record[1].push(hasSmall);
899 record[1].push(hasTiny);
900 record[1].push(hasOperand);
901 record[1].push(hasStop);
902 }
903 break;
caryclark03b03ca2015-04-23 09:13:37 -0700904 case REC_TYPE_TOP:
905 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
906" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
907 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
908" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
909 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
910" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
911 );
912 break;
caryclarkdac1d172014-06-17 05:15:38 -0700913 case REC_TYPE_MARK:
914 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700915" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700916 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700917" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700918 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
919" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700920 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700921" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
922 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
923" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
924 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
925" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
caryclark1049f122015-04-20 08:31:59 -0700926 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
927" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
caryclark54359292015-03-26 07:52:43 -0700928 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
929" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
caryclarkdac1d172014-06-17 05:15:38 -0700930 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
931" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
932 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
933" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700934 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
935" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700936 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
937" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700938 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -0700939" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -0700940 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
941" last segment=IDX span=IDX windSum=OPT");
caryclarkdac1d172014-06-17 05:15:38 -0700942 break;
943 case REC_TYPE_OP:
944 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
945 || line.lastIndexOf("operator<", 0) === 0) {
946 found = true;
947 break;
948 }
caryclark54359292015-03-26 07:52:43 -0700949 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -0700950 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -0700951 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -0700952 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
953 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
954 );
955 break;
956 case REC_TYPE_UNKNOWN:
957 found = true;
958 break;
959 }
960 if (!found) {
961 console.log(line + " [" + lineNo + "] of type " + type + " not found");
962 }
963 }
964 if (recType != REC_TYPE_UNKNOWN) {
965 records.push(recType);
966 records.push(lastLineNo);
967 records.push(record);
968 }
969 if (records.length >= 1) {
970 tests[testIndex] = records;
971 testLines[testIndex] = lines;
972 }
973}
974
975function init(test) {
976 var canvas = document.getElementById('canvas');
977 if (!canvas.getContext) return;
978 ctx = canvas.getContext('2d');
979 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
980 var unscaledWidth = window.innerWidth - 20;
981 var unscaledHeight = window.innerHeight - 20;
982 screenWidth = unscaledWidth;
983 screenHeight = unscaledHeight;
984 canvas.width = unscaledWidth * resScale;
985 canvas.height = unscaledHeight * resScale;
986 canvas.style.width = unscaledWidth + 'px';
987 canvas.style.height = unscaledHeight + 'px';
988 if (resScale != 1) {
989 ctx.scale(resScale, resScale);
990 }
991 xmin = Infinity;
992 xmax = -Infinity;
993 ymin = Infinity;
994 ymax = -Infinity;
caryclark26ad22a2015-10-16 09:03:38 -0700995 hasPath = hasAlignedPath = hasComputedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -0700996 firstActiveSpan = -1;
997 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
998 var recType = test[tIndex];
999 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
1000 console.log("unknown rec type: " + recType);
1001 throw "stop execution";
1002 }
1003 var records = test[tIndex + 2];
1004 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1005 var fragType = records[recordIndex];
1006 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
1007 console.log("unknown in range frag type: " + fragType);
1008 throw "stop execution";
1009 }
1010 var frags = records[recordIndex + 1];
1011 var first = 0;
1012 var last = -1;
1013 var first2 = 0;
1014 var last2 = 0;
1015 switch (recType) {
caryclark26ad22a2015-10-16 09:03:38 -07001016 case REC_TYPE_ALIGNED:
1017 hasAlignedPath = true;
caryclarkdac1d172014-06-17 05:15:38 -07001018 case REC_TYPE_COMPUTED:
1019 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
1020 break;
1021 }
caryclark26ad22a2015-10-16 09:03:38 -07001022 if (REC_TYPE_COMPUTED == recType) {
1023 hasComputedPath = true;
1024 }
caryclarkdac1d172014-06-17 05:15:38 -07001025 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001026 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -07001027 switch (fragType) {
1028 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07001029 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -07001030 break;
caryclark1049f122015-04-20 08:31:59 -07001031 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07001032 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07001033 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -07001034 break;
1035 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07001036 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -07001037 break;
1038 default:
1039 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
1040 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1041 throw "stop execution";
1042 }
1043 if (recType == REC_TYPE_PATH) {
1044 hasPath = true;
1045 }
1046 break;
caryclark54359292015-03-26 07:52:43 -07001047 case REC_TYPE_PATH2:
1048 first = 1;
1049 switch (fragType) {
1050 case PATH_LINE:
1051 last = 5;
1052 break;
caryclark1049f122015-04-20 08:31:59 -07001053 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001054 case PATH_QUAD:
1055 last = 7;
1056 break;
1057 case PATH_CUBIC:
1058 last = 9;
1059 break;
1060 default:
1061 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
1062 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1063 throw "stop execution";
1064 }
1065 if (recType == REC_TYPE_PATH2) {
1066 hasPath = true;
1067 }
1068 break;
caryclarkdac1d172014-06-17 05:15:38 -07001069 case REC_TYPE_ACTIVE:
1070 if (firstActiveSpan < 0) {
1071 firstActiveSpan = tIndex;
1072 }
1073 first = 1;
1074 switch (fragType) {
1075 case ACTIVE_LINE_SPAN:
1076 last = 5;
1077 break;
caryclark1049f122015-04-20 08:31:59 -07001078 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -07001079 case ACTIVE_QUAD_SPAN:
1080 last = 7;
1081 break;
1082 case ACTIVE_CUBIC_SPAN:
1083 last = 9;
1084 break;
1085 default:
1086 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1087 throw "stop execution";
1088 }
1089 break;
1090 case REC_TYPE_ADD:
1091 switch (fragType) {
1092 case ADD_MOVETO:
1093 break;
1094 case ADD_LINETO:
1095 last = 4;
1096 break;
caryclark1049f122015-04-20 08:31:59 -07001097 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -07001098 case ADD_QUADTO:
1099 last = 6;
1100 break;
1101 case ADD_CUBICTO:
1102 last = 8;
1103 break;
1104 case ADD_CLOSE:
1105 case ADD_FILL:
1106 break;
1107 default:
1108 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1109 throw "stop execution";
1110 }
1111 break;
caryclark54359292015-03-26 07:52:43 -07001112 case REC_TYPE_AFTERPART:
1113 switch (fragType) {
1114 case PATH_LINE:
1115 last = 4;
1116 break;
caryclark1049f122015-04-20 08:31:59 -07001117 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001118 case PATH_QUAD:
1119 last = 6;
1120 break;
1121 case PATH_CUBIC:
1122 last = 8;
1123 break;
1124 default:
1125 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1126 throw "stop execution";
1127 }
1128 break;
caryclarkdac1d172014-06-17 05:15:38 -07001129 case REC_TYPE_SECT:
1130 switch (fragType) {
1131 case INTERSECT_LINE:
1132 first = 1; last = 5; first2 = 8; last2 = 12;
1133 break;
1134 case INTERSECT_LINE_2:
1135 first = 1; last = 5; first2 = 11; last2 = 15;
1136 break;
1137 case INTERSECT_LINE_NO:
1138 first = 0; last = 4; first2 = 4; last2 = 8;
1139 break;
caryclark1049f122015-04-20 08:31:59 -07001140 case INTERSECT_CONIC_LINE:
1141 first = 1; last = 7; first2 = 11; last2 = 15;
1142 break;
caryclarkdac1d172014-06-17 05:15:38 -07001143 case INTERSECT_QUAD_LINE:
1144 first = 1; last = 7; first2 = 10; last2 = 14;
1145 break;
caryclark1049f122015-04-20 08:31:59 -07001146 case INTERSECT_CONIC_LINE_2:
1147 first = 1; last = 7; first2 = 14; last2 = 18;
1148 break;
caryclarkdac1d172014-06-17 05:15:38 -07001149 case INTERSECT_QUAD_LINE_2:
1150 first = 1; last = 7; first2 = 13; last2 = 17;
1151 break;
caryclark1049f122015-04-20 08:31:59 -07001152 case INTERSECT_CONIC_LINE_NO:
1153 first = 0; last = 6; first2 = 7; last2 = 11;
1154 break;
caryclarkdac1d172014-06-17 05:15:38 -07001155 case INTERSECT_QUAD_LINE_NO:
1156 first = 0; last = 6; first2 = 6; last2 = 10;
1157 break;
caryclark1049f122015-04-20 08:31:59 -07001158 case INTERSECT_CONIC:
1159 first = 1; last = 7; first2 = 11; last2 = 17;
1160 break;
caryclarkdac1d172014-06-17 05:15:38 -07001161 case INTERSECT_QUAD:
1162 first = 1; last = 7; first2 = 10; last2 = 16;
1163 break;
caryclark1049f122015-04-20 08:31:59 -07001164 case INTERSECT_CONIC_2:
1165 first = 1; last = 7; first2 = 14; last2 = 20;
1166 break;
caryclarkdac1d172014-06-17 05:15:38 -07001167 case INTERSECT_QUAD_2:
1168 first = 1; last = 7; first2 = 13; last2 = 19;
1169 break;
caryclark1049f122015-04-20 08:31:59 -07001170 case INTERSECT_CONIC_NO:
1171 first = 0; last = 6; first2 = 7; last2 = 13;
1172 break;
caryclarkdac1d172014-06-17 05:15:38 -07001173 case INTERSECT_QUAD_NO:
1174 first = 0; last = 6; first2 = 6; last2 = 12;
1175 break;
1176 case INTERSECT_SELF_CUBIC:
1177 first = 1; last = 9;
1178 break;
1179 case INTERSECT_SELF_CUBIC_NO:
1180 first = 0; last = 8;
1181 break;
1182 case INTERSECT_CUBIC_LINE:
1183 first = 1; last = 9; first2 = 12; last2 = 16;
1184 break;
1185 case INTERSECT_CUBIC_LINE_2:
1186 first = 1; last = 9; first2 = 15; last2 = 19;
1187 break;
1188 case INTERSECT_CUBIC_LINE_3:
1189 first = 1; last = 9; first2 = 18; last2 = 22;
1190 break;
1191 case INTERSECT_CUBIC_LINE_NO:
1192 first = 0; last = 8; first2 = 8; last2 = 12;
1193 break;
1194 case INTERSECT_CUBIC_QUAD:
1195 first = 1; last = 9; first2 = 12; last2 = 18;
1196 break;
1197 case INTERSECT_CUBIC_QUAD_2:
1198 first = 1; last = 9; first2 = 15; last2 = 21;
1199 break;
1200 case INTERSECT_CUBIC_QUAD_3:
1201 first = 1; last = 9; first2 = 18; last2 = 24;
1202 break;
1203 case INTERSECT_CUBIC_QUAD_4:
1204 first = 1; last = 9; first2 = 21; last2 = 27;
1205 break;
1206 case INTERSECT_CUBIC_QUAD_NO:
1207 first = 0; last = 8; first2 = 8; last2 = 14;
1208 break;
1209 case INTERSECT_CUBIC:
1210 first = 1; last = 9; first2 = 12; last2 = 20;
1211 break;
1212 case INTERSECT_CUBIC_2:
1213 first = 1; last = 9; first2 = 15; last2 = 23;
1214 break;
1215 case INTERSECT_CUBIC_3:
1216 first = 1; last = 9; first2 = 18; last2 = 26;
1217 break;
1218 case INTERSECT_CUBIC_4:
1219 first = 1; last = 9; first2 = 21; last2 = 29;
1220 break;
1221 case INTERSECT_CUBIC_NO:
1222 first = 0; last = 8; first2 = 8; last2 = 16;
1223 break;
1224 default:
1225 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1226 throw "stop execution";
1227 }
1228 break;
1229 default:
1230 continue;
1231 }
1232 for (var idx = first; idx < last; idx += 2) {
1233 xmin = Math.min(xmin, frags[idx]);
1234 xmax = Math.max(xmax, frags[idx]);
1235 ymin = Math.min(ymin, frags[idx + 1]);
1236 ymax = Math.max(ymax, frags[idx + 1]);
1237 }
1238 for (var idx = first2; idx < last2; idx += 2) {
1239 xmin = Math.min(xmin, frags[idx]);
1240 xmax = Math.max(xmax, frags[idx]);
1241 ymin = Math.min(ymin, frags[idx + 1]);
1242 ymax = Math.max(ymax, frags[idx + 1]);
1243 }
1244 }
1245 }
1246 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1247 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1248 var recType = test[tIndex];
1249 var records = test[tIndex + 2];
1250 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1251 var fragType = records[recordIndex];
1252 var frags = records[recordIndex + 1];
1253 switch (recType) {
1254 case REC_TYPE_ACTIVE_OP:
1255 if (!draw_op) {
1256 break;
1257 }
1258 {
1259 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1260 curve_extremes(curve, angleBounds);
1261 }
1262 break;
1263 case REC_TYPE_ANGLE:
1264 if (!draw_angle) {
1265 break;
1266 }
caryclark54359292015-03-26 07:52:43 -07001267 {
caryclarkdac1d172014-06-17 05:15:38 -07001268 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1269 curve_extremes(curve, angleBounds);
1270 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1271 curve_extremes(curve, angleBounds);
1272 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1273 }
1274 break;
caryclark624637c2015-05-11 07:21:27 -07001275 case REC_TYPE_COINCIDENCE:
1276 if (!draw_coincidence) {
1277 break;
1278 }
1279 {
1280 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1281 curve_extremes(curve, angleBounds);
1282 }
1283 break;
caryclarkdac1d172014-06-17 05:15:38 -07001284 case REC_TYPE_SORT:
1285 if (!draw_sort) {
1286 break;
1287 }
1288 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1289 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1290 curve_extremes(curve, angleBounds);
1291 }
1292 break;
caryclark03b03ca2015-04-23 09:13:37 -07001293 case REC_TYPE_TOP:
1294 if (!draw_top) {
1295 break;
1296 }
1297 {
1298 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1299 curve_extremes(curve, angleBounds);
1300 }
1301 break;
caryclarkdac1d172014-06-17 05:15:38 -07001302 }
1303 }
1304 }
1305 xmin = Math.min(xmin, angleBounds[0]);
1306 ymin = Math.min(ymin, angleBounds[1]);
1307 xmax = Math.max(xmax, angleBounds[2]);
1308 ymax = Math.max(ymax, angleBounds[3]);
1309 setScale(xmin, xmax, ymin, ymax);
1310 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001311 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001312 }
1313 if (hasPath == true && hasComputedPath == false && draw_computed) {
1314 draw_computed = 0;
1315 }
1316}
1317
caryclark26ad22a2015-10-16 09:03:38 -07001318function curveByIDMatch(test, id, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001319 var tIndex = -3;
1320 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001321 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001322 if (recType == REC_TYPE_OP) {
1323 continue;
1324 }
caryclark26ad22a2015-10-16 09:03:38 -07001325 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001326 return [];
1327 }
1328 var records = test[tIndex + 2];
1329 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1330 var fragType = records[recordIndex];
1331 var frags = records[recordIndex + 1];
1332 if (frags[0] == id) {
1333 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001334 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001335 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001336 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001337 return [frags[1], frags[2], frags[3], frags[4],
1338 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001339 case PATH_CONIC:
1340 return [frags[1], frags[2], frags[3], frags[4],
1341 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001342 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001343 return [frags[1], frags[2], frags[3], frags[4],
1344 frags[5], frags[6], frags[7], frags[8]];
1345 }
1346 }
1347 }
caryclarkdac1d172014-06-17 05:15:38 -07001348 }
1349 return [];
1350}
1351
caryclark26ad22a2015-10-16 09:03:38 -07001352function curveByID(test, id) {
1353 var result = draw_path >= 4 ? curveByIDMatch(test, id, REC_TYPE_ALIGNED) : [];
1354 if (!result.length) {
1355 result = curveByIDMatch(test, id, REC_TYPE_PATH);
1356 }
1357 return result;
1358}
1359
1360function curvePartialByIDMatch(test, id, t0, t1, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001361 var tIndex = -3;
1362 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001363 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001364 if (recType == REC_TYPE_OP) {
1365 continue;
1366 }
caryclark26ad22a2015-10-16 09:03:38 -07001367 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001368 return [];
1369 }
1370 var records = test[tIndex + 2];
1371 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1372 var fragType = records[recordIndex];
1373 var frags = records[recordIndex + 1];
1374 if (frags[0] == id) {
1375 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001376 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001377 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001378 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001379 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1380 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001381 case PATH_CONIC:
1382 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1383 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001384 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001385 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1386 frags[5], frags[6], frags[7], frags[8], t0, t1);
1387 }
1388 }
1389 }
caryclarkdac1d172014-06-17 05:15:38 -07001390 }
1391 return [];
1392}
1393
caryclark26ad22a2015-10-16 09:03:38 -07001394function curvePartialByID(test, id, t0, t1) {
1395 var result = draw_path >= 4 ? curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_ALIGNED) : [];
1396 if (!result.length) {
1397 result = curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_PATH);
1398 }
1399 return result;
1400}
1401
1402function idByCurveIDMatch(test, frag, type, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001403 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001404 while (tIndex < test.length) {
1405 var recType = test[tIndex];
caryclark26ad22a2015-10-16 09:03:38 -07001406 if (recType != recMatch) {
caryclark54359292015-03-26 07:52:43 -07001407 ++tIndex;
1408 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001409 }
1410 var records = test[tIndex + 2];
1411 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1412 var fragType = records[recordIndex];
1413 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001414 if (frag.length != frags.length - 1) {
1415 continue;
1416 }
caryclarkdac1d172014-06-17 05:15:38 -07001417 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001418 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001419 if (frag[0] != frags[1] || frag[1] != frags[2]
1420 || frag[2] != frags[3] || frag[3] != frags[4]) {
1421 continue;
1422 }
1423 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001424 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001425 if (frag[0] != frags[1] || frag[1] != frags[2]
1426 || frag[2] != frags[3] || frag[3] != frags[4]
1427 || frag[4] != frags[5] || frag[5] != frags[6]) {
1428 continue;
1429 }
1430 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001431 case PATH_CONIC:
1432 if (frag[0] != frags[1] || frag[1] != frags[2]
1433 || frag[2] != frags[3] || frag[3] != frags[4]
1434 || frag[4] != frags[5] || frag[5] != frags[6]
1435 || frag[6] != frags[7]) {
1436 continue;
1437 }
1438 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001439 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001440 if (frag[0] != frags[1] || frag[1] != frags[2]
1441 || frag[2] != frags[3] || frag[3] != frags[4]
1442 || frag[4] != frags[5] || frag[5] != frags[6]
1443 || frag[6] != frags[7] || frag[7] != frags[8]) {
1444 continue;
1445 }
1446 return frags[0];
1447 }
1448 }
1449 ++tIndex;
1450 }
1451 return -1;
1452}
1453
caryclark26ad22a2015-10-16 09:03:38 -07001454function idByCurve(test, frag, type) {
1455 var result = draw_path >= 4 ? idByCurveIDMatch(test, frag, type, REC_TYPE_ALIGNED) : [];
1456 if (!result.length) {
1457 result = idByCurveIDMatch(test, frag, type, REC_TYPE_PATH);
1458 }
1459 return result;
1460}
1461
caryclarkdac1d172014-06-17 05:15:38 -07001462function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001463 var length = curve.length == 7 ? 6 : curve.length;
caryclarkdac1d172014-06-17 05:15:38 -07001464 for (var index = 0; index < curve.length; index += 2) {
1465 var x = curve[index];
1466 var y = curve[index + 1];
1467 bounds[0] = Math.min(bounds[0], x);
1468 bounds[1] = Math.min(bounds[1], y);
1469 bounds[2] = Math.max(bounds[2], x);
1470 bounds[3] = Math.max(bounds[3], y);
1471 }
1472}
1473
1474function setScale(x0, x1, y0, y1) {
1475 var srcWidth = x1 - x0;
1476 var srcHeight = y1 - y0;
1477 var usableWidth = screenWidth;
1478 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1479 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1480 usableWidth -= (xDigits + yDigits) * 10;
1481 usableWidth -= decimal_places * 10;
1482 if (draw_legend) {
1483 usableWidth -= 40;
1484 }
1485 var hscale = usableWidth / srcWidth;
1486 var vscale = screenHeight / srcHeight;
1487 scale = Math.min(hscale, vscale);
1488 var invScale = 1 / scale;
1489 var sxmin = x0 - invScale * 5;
1490 var symin = y0 - invScale * 10;
1491 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1492 var symax = y1 + invScale * 10;
1493 srcWidth = sxmax - sxmin;
1494 srcHeight = symax - symin;
1495 hscale = usableWidth / srcWidth;
1496 vscale = screenHeight / srcHeight;
1497 scale = Math.min(hscale, vscale);
1498 srcLeft = sxmin;
1499 srcTop = symin;
1500}
1501
1502function drawArc(curve, op, from, to) {
1503 var type = PATH_LINE + (curve.length / 2 - 2);
1504 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1505 var dy = pt.y - curve[1];
1506 var dx = pt.x - curve[0];
1507 var dist = Math.sqrt(dy * dy + dx * dx);
1508 var _dist = dist * scale;
1509 var angle = Math.atan2(dy, dx);
1510 var _px = (curve[0] - srcLeft) * scale;
1511 var _py = (curve[1] - srcTop) * scale;
1512 var divisor = 4;
1513 var endDist;
1514 do {
1515 var ends = [];
1516 for (var index = -1; index <= 1; index += 2) {
1517 var px = Math.cos(index * Math.PI / divisor);
1518 var py = Math.sin(index * Math.PI / divisor);
1519 ends.push(px);
1520 ends.push(py);
1521 }
1522 var endDx = (ends[2] - ends[0]) * scale * dist;
1523 var endDy = (ends[3] - ends[1]) * scale * dist;
1524 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1525 if (endDist < 100) {
1526 break;
1527 }
1528 divisor *= 2;
1529 } while (true);
1530 if (endDist < 30) {
1531 return;
1532 }
1533 if (op) {
1534 divisor *= 2;
1535 }
1536 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1537 ctx.beginPath();
1538 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1539 ctx.stroke();
1540 var saveAlign = ctx.textAlign;
1541 var saveStyle = ctx.fillStyle;
1542 var saveFont = ctx.font;
1543 ctx.textAlign = "center";
1544 ctx.fillStyle = "black";
1545 ctx.font = "normal 24px Arial";
1546 divisor *= 0.8;
1547 for (var index = -1; index <= 1; index += 2) {
1548 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1549 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1550 var _px = (px - srcLeft) * scale;
1551 var _py = (py - srcTop) * scale;
1552 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1553 }
1554 ctx.textAlign = saveAlign;
1555 ctx.fillStyle = saveStyle;
1556 ctx.font = saveFont;
1557}
1558
1559function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001560 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1561 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001562 var x = drawnPts[pts];
1563 var y = drawnPts[pts + 1];
1564 if (px == x && py == y) {
1565 return;
1566 }
1567 }
1568 drawnPts.push(px);
1569 drawnPts.push(py);
1570 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1571 var _px = (px - srcLeft) * scale;
1572 var _py = (py - srcTop) * scale;
1573 ctx.beginPath();
1574 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1575 ctx.closePath();
1576 if (end) {
1577 ctx.fill();
1578 } else {
1579 ctx.stroke();
1580 }
1581 if (debug_xy) {
1582 ctx.textAlign = "left";
1583 ctx.fillText(label, _px + 5, _py);
1584 }
1585}
1586
caryclark1049f122015-04-20 08:31:59 -07001587function coordCount(curveType) {
1588 switch (curveType) {
1589 case PATH_LINE:
1590 return 4;
1591 case PATH_QUAD:
1592 return 6;
1593 case PATH_CONIC:
1594 return 6;
1595 case PATH_CUBIC:
1596 return 8;
1597 }
1598 return -1;
1599}
1600
caryclarkdac1d172014-06-17 05:15:38 -07001601function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001602 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001603 for (var idx = 0; idx < count; idx += 2) {
1604 if (!drawControls && idx != 0 && idx != count - 2) {
1605 continue;
1606 }
1607 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1608 }
1609}
1610
1611function drawControlLines(curve, curveType, drawEnd) {
1612 if (curveType == PATH_LINE) {
1613 return;
1614 }
1615 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1616 drawLine(curve[0], curve[1], curve[2], curve[3]);
1617 drawLine(curve[2], curve[3], curve[4], curve[5]);
1618 if (curveType == PATH_CUBIC) {
1619 drawLine(curve[4], curve[5], curve[6], curve[7]);
1620 if (drawEnd > 1) {
1621 drawLine(curve[6], curve[7], curve[0], curve[1]);
1622 if (drawEnd > 2) {
1623 drawLine(curve[0], curve[1], curve[4], curve[5]);
1624 drawLine(curve[6], curve[7], curve[2], curve[3]);
1625 }
1626 }
1627 } else if (drawEnd > 1) {
1628 drawLine(curve[4], curve[5], curve[0], curve[1]);
1629 }
1630}
1631
1632function pointAtT(curve, curveType, t) {
1633 var xy = {};
1634 switch (curveType) {
1635 case PATH_LINE:
1636 var a = 1 - t;
1637 var b = t;
1638 xy.x = a * curve[0] + b * curve[2];
1639 xy.y = a * curve[1] + b * curve[3];
1640 break;
1641 case PATH_QUAD:
1642 var one_t = 1 - t;
1643 var a = one_t * one_t;
1644 var b = 2 * one_t * t;
1645 var c = t * t;
1646 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1647 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1648 break;
caryclark1049f122015-04-20 08:31:59 -07001649 case PATH_CONIC:
1650 var one_t = 1 - t;
1651 var a = one_t * one_t;
1652 var b = 2 * one_t * t;
1653 var c = t * t;
1654 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1655 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1656 var d = a + b * curve[6] + c;
1657 xy.x /= d;
1658 xy.y /= d;
1659 break;
caryclarkdac1d172014-06-17 05:15:38 -07001660 case PATH_CUBIC:
1661 var one_t = 1 - t;
1662 var one_t2 = one_t * one_t;
1663 var a = one_t2 * one_t;
1664 var b = 3 * one_t2 * t;
1665 var t2 = t * t;
1666 var c = 3 * one_t * t2;
1667 var d = t2 * t;
1668 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1669 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1670 break;
1671 }
1672 return xy;
1673}
1674
1675function drawPointAtT(curve, curveType) {
1676 var x, y;
1677 var xy = pointAtT(curve, curveType, curveT);
1678 drawPoint(xy.x, xy.y, true);
1679 if (!draw_intersectT) {
1680 return;
1681 }
1682 ctx.fillStyle = "red";
1683 drawTAtPointUp(xy.x, xy.y, curveT);
1684}
1685
1686function drawTAtPointUp(px, py, t) {
1687 var label = t.toFixed(decimal_places);
1688 var _px = (px - srcLeft)* scale;
1689 var _py = (py - srcTop) * scale;
1690 ctx.fillText(label, _px + 5, _py - 10);
1691}
1692
1693function drawTAtPointDown(px, py, t) {
1694 var label = t.toFixed(decimal_places);
1695 var _px = (px - srcLeft)* scale;
1696 var _py = (py - srcTop) * scale;
1697 ctx.fillText(label, _px + 5, _py + 10);
1698}
1699
1700function alreadyDrawnLine(x1, y1, x2, y2) {
1701 if (collect_bounds) {
1702 if (focus_enabled) {
1703 focusXmin = Math.min(focusXmin, x1, x2);
1704 focusYmin = Math.min(focusYmin, y1, y2);
1705 focusXmax = Math.max(focusXmax, x1, x2);
1706 focusYmax = Math.max(focusYmax, y1, y2);
1707 }
1708 return true;
1709 }
1710 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1711 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1712 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1713 return true;
1714 }
1715 }
1716 drawnLines.push(x1);
1717 drawnLines.push(y1);
1718 drawnLines.push(x2);
1719 drawnLines.push(y2);
1720 return false;
1721}
1722
1723function drawLine(x1, y1, x2, y2) {
1724 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1725 return;
1726 }
1727 ctx.beginPath();
1728 ctx.moveTo((x1 - srcLeft) * scale,
1729 (y1 - srcTop) * scale);
1730 ctx.lineTo((x2 - srcLeft) * scale,
1731 (y2 - srcTop) * scale);
1732 ctx.stroke();
1733}
1734
1735function linePartial(x1, y1, x2, y2, t1, t2) {
1736 var dx = x1 - x2;
1737 var dy = y1 - y2;
1738 var array = [
1739 x1 - t1 * dx,
1740 y1 - t1 * dy,
1741 x1 - t2 * dx,
1742 y1 - t2 * dy
1743 ];
1744 return array;
1745}
1746
1747function drawLinePartial(x1, y1, x2, y2, t1, t2) {
1748 var a = linePartial(x1, y1, x2, y2, t1, t2);
1749 var ax = a[0];
1750 var ay = a[1];
1751 var bx = a[2];
1752 var by = a[3];
1753 if (alreadyDrawnLine(ax, ay, bx, by)) {
1754 return;
1755 }
1756 ctx.beginPath();
1757 ctx.moveTo((ax - srcLeft) * scale,
1758 (ay - srcTop) * scale);
1759 ctx.lineTo((bx - srcLeft) * scale,
1760 (by - srcTop) * scale);
1761 ctx.stroke();
1762}
1763
1764function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
1765 if (collect_bounds) {
1766 if (focus_enabled) {
1767 focusXmin = Math.min(focusXmin, x1, x2, x3);
1768 focusYmin = Math.min(focusYmin, y1, y2, y3);
1769 focusXmax = Math.max(focusXmax, x1, x2, x3);
1770 focusYmax = Math.max(focusYmax, y1, y2, y3);
1771 }
1772 return true;
1773 }
1774 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
1775 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
1776 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
1777 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
1778 return true;
1779 }
1780 }
1781 drawnQuads.push(x1);
1782 drawnQuads.push(y1);
1783 drawnQuads.push(x2);
1784 drawnQuads.push(y2);
1785 drawnQuads.push(x3);
1786 drawnQuads.push(y3);
1787 return false;
1788}
1789
1790function drawQuad(x1, y1, x2, y2, x3, y3) {
1791 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
1792 return;
1793 }
1794 ctx.beginPath();
1795 ctx.moveTo((x1 - srcLeft) * scale,
1796 (y1 - srcTop) * scale);
1797 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
1798 (y2 - srcTop) * scale,
1799 (x3 - srcLeft) * scale,
1800 (y3 - srcTop) * scale);
1801 ctx.stroke();
1802}
1803
1804function interp(A, B, t) {
1805 return A + (B - A) * t;
1806}
1807
1808function interp_quad_coords(x1, x2, x3, t)
1809{
1810 var ab = interp(x1, x2, t);
1811 var bc = interp(x2, x3, t);
1812 var abc = interp(ab, bc, t);
1813 return abc;
1814}
1815
1816function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1817 var ax = interp_quad_coords(x1, x2, x3, t1);
1818 var ay = interp_quad_coords(y1, y2, y3, t1);
1819 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
1820 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
1821 var cx = interp_quad_coords(x1, x2, x3, t2);
1822 var cy = interp_quad_coords(y1, y2, y3, t2);
1823 var bx = 2*dx - (ax + cx)/2;
1824 var by = 2*dy - (ay + cy)/2;
1825 var array = [
1826 ax, ay, bx, by, cx, cy
1827 ];
1828 return array;
1829}
1830
1831function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1832 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
1833 var ax = a[0];
1834 var ay = a[1];
1835 var bx = a[2];
1836 var by = a[3];
1837 var cx = a[4];
1838 var cy = a[5];
1839 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
1840 return;
1841 }
1842 ctx.beginPath();
1843 ctx.moveTo((ax - srcLeft) * scale,
1844 (ay - srcTop) * scale);
1845 ctx.quadraticCurveTo((bx - srcLeft) * scale,
1846 (by - srcTop) * scale,
1847 (cx - srcLeft) * scale,
1848 (cy - srcTop) * scale);
1849 ctx.stroke();
1850}
1851
caryclark1049f122015-04-20 08:31:59 -07001852function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
1853 if (collect_bounds) {
1854 if (focus_enabled) {
1855 focusXmin = Math.min(focusXmin, x1, x2, x3);
1856 focusYmin = Math.min(focusYmin, y1, y2, y3);
1857 focusXmax = Math.max(focusXmax, x1, x2, x3);
1858 focusYmax = Math.max(focusYmax, y1, y2, y3);
1859 }
1860 return true;
1861 }
1862 for (var pts = 0; pts < drawnConics.length; pts += 8) {
1863 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
1864 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1865 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1866 && w == drawnCubics[pts + 6]) {
1867 return true;
1868 }
1869 }
1870 drawnConics.push(x1);
1871 drawnConics.push(y1);
1872 drawnConics.push(x2);
1873 drawnConics.push(y2);
1874 drawnConics.push(x3);
1875 drawnConics.push(y3);
1876 drawnCubics.push(w);
1877 return false;
1878}
1879
1880var kMaxConicToQuadPOW2 = 5;
1881
1882function computeQuadPOW2(curve, tol) {
1883 var a = curve[6] - 1;
1884 var k = a / (4 * (2 + a));
1885 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
1886 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
1887
1888 var error = Math.sqrt(x * x + y * y);
1889 var pow2;
1890 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
1891 if (error <= tol) {
1892 break;
1893 }
1894 error *= 0.25;
1895 }
1896 return pow2;
1897}
1898
1899function subdivide_w_value(w) {
1900 return Math.sqrt(0.5 + w * 0.5);
1901}
1902
1903function chop(curve, part1, part2) {
1904 var w = curve[6];
1905 var scale = 1 / (1 + w);
1906 part1[0] = curve[0];
1907 part1[1] = curve[1];
1908 part1[2] = (curve[0] + curve[2] * w) * scale;
1909 part1[3] = (curve[1] + curve[3] * w) * scale;
1910 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
1911 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
1912 part2[2] = (curve[2] * w + curve[4]) * scale;
1913 part2[3] = (curve[3] * w + curve[5]) * scale;
1914 part2[4] = curve[4];
1915 part2[5] = curve[5];
1916 part1[6] = part2[6] = subdivide_w_value(w);
1917}
1918
1919function subdivide(curve, level, pts) {
1920 if (0 == level) {
1921 pts.push(curve[2]);
1922 pts.push(curve[3]);
1923 pts.push(curve[4]);
1924 pts.push(curve[5]);
1925 } else {
1926 var part1 = [], part2 = [];
1927 chop(curve, part1, part2);
1928 --level;
1929 subdivide(part1, level, pts);
1930 subdivide(part2, level, pts);
1931 }
1932}
1933
1934function chopIntoQuadsPOW2(curve, pow2, pts) {
1935 subdivide(curve, pow2, pts);
1936 return 1 << pow2;
1937}
1938
1939function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
1940 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
1941 return;
1942 }
1943 ctx.beginPath();
1944 ctx.moveTo((x1 - srcLeft) * scale,
1945 (y1 - srcTop) * scale);
1946 var tol = 1 / scale;
1947 var curve = [x1, y1, x2, y2, x3, y3, w];
1948 var pow2 = computeQuadPOW2(curve, tol);
1949 var pts = [];
1950 chopIntoQuadsPOW2(curve, pow2, pts);
1951 for (var i = 0; i < pts.length; i += 4) {
1952 ctx.quadraticCurveTo(
1953 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
1954 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
1955 }
1956 ctx.stroke();
1957}
1958
1959function conic_eval_numerator(x1, x2, x3, w, t) {
1960 var src2w = x2 * w;
1961 var C = x1;
1962 var A = x3 - 2 * src2w + C;
1963 var B = 2 * (src2w - C);
1964 return (A * t + B) * t + C;
1965}
1966
1967
1968function conic_eval_denominator(w, t) {
1969 var B = 2 * (w - 1);
1970 var C = 1;
1971 var A = -B;
1972 return (A * t + B) * t + C;
1973}
1974
1975function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
1976 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
1977 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
1978 var az = conic_eval_denominator(w, t1);
1979 var midT = (t1 + t2) / 2;
1980 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
1981 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
1982 var dz = conic_eval_denominator(w, midT);
1983 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
1984 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
1985 var cz = conic_eval_denominator(w, t2);
1986 var bx = 2 * dx - (ax + cx) / 2;
1987 var by = 2 * dy - (ay + cy) / 2;
1988 var bz = 2 * dz - (az + cz) / 2;
1989 var dt = t2 - t1;
1990 var dt_1 = 1 - dt;
1991 var partW = (1 + dt * (w - 1)) / Math.sqrt(dt * dt + 2 * dt * dt_1 * w + dt_1 * dt_1);
1992 var array = [
1993 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, partW
1994 ];
1995 return array;
1996}
1997
1998function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
1999 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2000 var ax = a[0];
2001 var ay = a[1];
2002 var bx = a[2];
2003 var by = a[3];
2004 var cx = a[4];
2005 var cy = a[5];
2006 var w_ = a[6];
2007 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
2008}
2009
caryclarkdac1d172014-06-17 05:15:38 -07002010function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2011 if (collect_bounds) {
2012 if (focus_enabled) {
2013 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
2014 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
2015 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
2016 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
2017 }
2018 return true;
2019 }
2020 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
2021 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
2022 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2023 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
2024 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
2025 return true;
2026 }
2027 }
2028 drawnCubics.push(x1);
2029 drawnCubics.push(y1);
2030 drawnCubics.push(x2);
2031 drawnCubics.push(y2);
2032 drawnCubics.push(x3);
2033 drawnCubics.push(y3);
2034 drawnCubics.push(x4);
2035 drawnCubics.push(y4);
2036 return false;
2037}
2038
2039function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2040 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
2041 return;
2042 }
2043 ctx.beginPath();
2044 ctx.moveTo((x1 - srcLeft) * scale,
2045 (y1 - srcTop) * scale);
2046 ctx.bezierCurveTo((x2 - srcLeft) * scale,
2047 (y2 - srcTop) * scale,
2048 (x3 - srcLeft) * scale,
2049 (y3 - srcTop) * scale,
2050 (x4 - srcLeft) * scale,
2051 (y4 - srcTop) * scale);
2052 ctx.stroke();
2053}
2054
2055function interp_cubic_coords(x1, x2, x3, x4, t)
2056{
2057 var ab = interp(x1, x2, t);
2058 var bc = interp(x2, x3, t);
2059 var cd = interp(x3, x4, t);
2060 var abc = interp(ab, bc, t);
2061 var bcd = interp(bc, cd, t);
2062 var abcd = interp(abc, bcd, t);
2063 return abcd;
2064}
2065
2066function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2067 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
2068 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
2069 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
2070 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
2071 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
2072 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
2073 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
2074 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
2075 var mx = ex * 27 - ax * 8 - dx;
2076 var my = ey * 27 - ay * 8 - dy;
2077 var nx = fx * 27 - ax - dx * 8;
2078 var ny = fy * 27 - ay - dy * 8;
2079 var bx = (mx * 2 - nx) / 18;
2080 var by = (my * 2 - ny) / 18;
2081 var cx = (nx * 2 - mx) / 18;
2082 var cy = (ny * 2 - my) / 18;
2083 var array = [
2084 ax, ay, bx, by, cx, cy, dx, dy
2085 ];
2086 return array;
2087}
2088
2089function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2090 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2091 var ax = a[0];
2092 var ay = a[1];
2093 var bx = a[2];
2094 var by = a[3];
2095 var cx = a[4];
2096 var cy = a[5];
2097 var dx = a[6];
2098 var dy = a[7];
2099 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
2100 return;
2101 }
2102 ctx.beginPath();
2103 ctx.moveTo((ax - srcLeft) * scale,
2104 (ay - srcTop) * scale);
2105 ctx.bezierCurveTo((bx - srcLeft) * scale,
2106 (by - srcTop) * scale,
2107 (cx - srcLeft) * scale,
2108 (cy - srcTop) * scale,
2109 (dx - srcLeft) * scale,
2110 (dy - srcTop) * scale);
2111 ctx.stroke();
2112}
2113
2114function drawCurve(c) {
2115 switch (c.length) {
2116 case 4:
2117 drawLine(c[0], c[1], c[2], c[3]);
2118 break;
2119 case 6:
2120 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
2121 break;
caryclark1049f122015-04-20 08:31:59 -07002122 case 7:
2123 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
2124 break;
caryclarkdac1d172014-06-17 05:15:38 -07002125 case 8:
2126 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
2127 break;
2128 }
2129}
2130
2131function boundsWidth(pts) {
2132 var min = pts[0];
2133 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07002134 var length = pts.length == 7 ? 6 : pts.length;
2135 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002136 min = Math.min(min, pts[idx]);
2137 max = Math.max(max, pts[idx]);
2138 }
2139 return max - min;
2140}
2141
2142function boundsHeight(pts) {
2143 var min = pts[1];
2144 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07002145 var length = pts.length == 7 ? 6 : pts.length;
2146 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002147 min = Math.min(min, pts[idx]);
2148 max = Math.max(max, pts[idx]);
2149 }
2150 return max - min;
2151}
2152
2153function tangent(pts) {
2154 var dx = pts[2] - pts[0];
2155 var dy = pts[3] - pts[1];
2156 if (dx == 0 && dy == 0 && pts.length > 4) {
2157 dx = pts[4] - pts[0];
2158 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002159 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002160 dx = pts[6] - pts[0];
2161 dy = pts[7] - pts[1];
2162 }
2163 }
2164 return Math.atan2(-dy, dx);
2165}
2166
2167function hodograph(cubic) {
2168 var hodo = [];
2169 hodo[0] = 3 * (cubic[2] - cubic[0]);
2170 hodo[1] = 3 * (cubic[3] - cubic[1]);
2171 hodo[2] = 3 * (cubic[4] - cubic[2]);
2172 hodo[3] = 3 * (cubic[5] - cubic[3]);
2173 hodo[4] = 3 * (cubic[6] - cubic[4]);
2174 hodo[5] = 3 * (cubic[7] - cubic[5]);
2175 return hodo;
2176}
2177
2178function hodograph2(cubic) {
2179 var quad = hodograph(cubic);
2180 var hodo = [];
2181 hodo[0] = 2 * (quad[2] - quad[0]);
2182 hodo[1] = 2 * (quad[3] - quad[1]);
2183 hodo[2] = 2 * (quad[4] - quad[2]);
2184 hodo[3] = 2 * (quad[5] - quad[3]);
2185 return hodo;
2186}
2187
2188function quadraticRootsReal(A, B, C, s) {
2189 if (A == 0) {
2190 if (B == 0) {
2191 s[0] = 0;
2192 return C == 0;
2193 }
2194 s[0] = -C / B;
2195 return 1;
2196 }
2197 /* normal form: x^2 + px + q = 0 */
2198 var p = B / (2 * A);
2199 var q = C / A;
2200 var p2 = p * p;
2201 if (p2 < q) {
2202 return 0;
2203 }
2204 var sqrt_D = 0;
2205 if (p2 > q) {
2206 sqrt_D = sqrt(p2 - q);
2207 }
2208 s[0] = sqrt_D - p;
2209 s[1] = -sqrt_D - p;
2210 return 1 + s[0] != s[1];
2211}
2212
2213function add_valid_ts(s, realRoots, t) {
2214 var foundRoots = 0;
2215 for (var index = 0; index < realRoots; ++index) {
2216 var tValue = s[index];
2217 if (tValue >= 0 && tValue <= 1) {
2218 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2219 if (t[idx2] != tValue) {
2220 t[foundRoots++] = tValue;
2221 }
2222 }
2223 }
2224 }
2225 return foundRoots;
2226}
2227
2228function quadraticRootsValidT(a, b, c, t) {
2229 var s = [];
2230 var realRoots = quadraticRootsReal(A, B, C, s);
2231 var foundRoots = add_valid_ts(s, realRoots, t);
2232 return foundRoots != 0;
2233}
2234
2235function find_cubic_inflections(cubic, tValues) {
2236 var Ax = src[2] - src[0];
2237 var Ay = src[3] - src[1];
2238 var Bx = src[4] - 2 * src[2] + src[0];
2239 var By = src[5] - 2 * src[3] + src[1];
2240 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2241 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2242 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2243 Ax * By - Ay * Bx, tValues);
2244}
2245
2246function dxy_at_t(curve, type, t) {
2247 var dxy = {};
2248 if (type == PATH_QUAD) {
2249 var a = t - 1;
2250 var b = 1 - 2 * t;
2251 var c = t;
2252 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2253 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002254 } else if (type == PATH_CONIC) {
2255 var p20x = curve[4] - curve[0];
2256 var p20y = curve[5] - curve[1];
2257 var p10xw = (curve[2] - curve[0]) * curve[6];
2258 var p10yw = (curve[3] - curve[1]) * curve[6];
2259 var coeff0x = curve[6] * p20x - p20x;
2260 var coeff0y = curve[6] * p20y - p20y;
2261 var coeff1x = p20x - 2 * p10xw;
2262 var coeff1y = p20y - 2 * p10yw;
2263 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2264 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002265 } else if (type == PATH_CUBIC) {
2266 var one_t = 1 - t;
2267 var a = curve[0];
2268 var b = curve[2];
2269 var c = curve[4];
2270 var d = curve[6];
2271 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2272 a = curve[1];
2273 b = curve[3];
2274 c = curve[5];
2275 d = curve[7];
2276 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2277 }
2278 return dxy;
2279}
2280
2281function drawLabel(num, px, py) {
2282 ctx.beginPath();
2283 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2284 ctx.closePath();
2285 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2286 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2287 ctx.stroke();
2288 ctx.fillStyle = "black";
2289 ctx.font = "normal 10px Arial";
2290 // ctx.rotate(0.001);
2291 ctx.fillText(num, px - 2, py + 3);
2292 // ctx.rotate(-0.001);
2293}
2294
2295function drawLabelX(ymin, num, loc) {
2296 var px = (loc - srcLeft) * scale;
2297 var py = (ymin - srcTop) * scale - 20;
2298 drawLabel(num, px, py);
2299}
2300
2301function drawLabelY(xmin, num, loc) {
2302 var px = (xmin - srcLeft) * scale - 20;
2303 var py = (loc - srcTop) * scale;
2304 drawLabel(num, px, py);
2305}
2306
2307function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2308 ctx.beginPath();
2309 ctx.moveTo(hx, hy - 100);
2310 ctx.lineTo(hx, hy);
2311 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2312 ctx.stroke();
2313 ctx.beginPath();
2314 ctx.moveTo(hx, hy);
2315 ctx.lineTo(hx, hy + 100);
2316 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2317 ctx.stroke();
2318 ctx.beginPath();
2319 ctx.moveTo(hx - 100, hy);
2320 ctx.lineTo(hx, hy);
2321 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2322 ctx.stroke();
2323 ctx.beginPath();
2324 ctx.moveTo(hx, hy);
2325 ctx.lineTo(hx + 100, hy);
2326 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2327 ctx.stroke();
2328}
2329
2330function scalexy(x, y, mag) {
2331 var length = Math.sqrt(x * x + y * y);
2332 return mag / length;
2333}
2334
caryclark03b03ca2015-04-23 09:13:37 -07002335function drawArrow(x, y, dx, dy, s) {
2336 var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
caryclarkdac1d172014-06-17 05:15:38 -07002337 dx *= dscale;
2338 dy *= dscale;
2339 ctx.beginPath();
2340 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2341 x += dx;
2342 y += dy;
2343 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2344 dx /= 10;
2345 dy /= 10;
2346 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2347 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2348 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2349 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2350 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2351 ctx.stroke();
2352}
2353
2354function x_at_t(curve, t) {
2355 var one_t = 1 - t;
2356 if (curve.length == 4) {
2357 return one_t * curve[0] + t * curve[2];
2358 }
2359 var one_t2 = one_t * one_t;
2360 var t2 = t * t;
2361 if (curve.length == 6) {
2362 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2363 }
caryclark1049f122015-04-20 08:31:59 -07002364 if (curve.length == 7) {
2365 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2366 / (one_t2 +2 * one_t * t * curve[6] + t2);
2367 }
caryclarkdac1d172014-06-17 05:15:38 -07002368 var a = one_t2 * one_t;
2369 var b = 3 * one_t2 * t;
2370 var c = 3 * one_t * t2;
2371 var d = t2 * t;
2372 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2373}
2374
2375function y_at_t(curve, t) {
2376 var one_t = 1 - t;
2377 if (curve.length == 4) {
2378 return one_t * curve[1] + t * curve[3];
2379 }
2380 var one_t2 = one_t * one_t;
2381 var t2 = t * t;
2382 if (curve.length == 6) {
2383 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2384 }
caryclark1049f122015-04-20 08:31:59 -07002385 if (curve.length == 7) {
2386 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2387 / (one_t2 +2 * one_t * t * curve[6] + t2);
2388 }
caryclarkdac1d172014-06-17 05:15:38 -07002389 var a = one_t2 * one_t;
2390 var b = 3 * one_t2 * t;
2391 var c = 3 * one_t * t2;
2392 var d = t2 * t;
2393 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2394}
2395
2396function drawOrder(curve, label) {
2397 var px = x_at_t(curve, 0.75);
2398 var py = y_at_t(curve, 0.75);
2399 var _px = (px - srcLeft) * scale;
2400 var _py = (py - srcTop) * scale;
2401 ctx.beginPath();
2402 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2403 ctx.closePath();
2404 ctx.fillStyle = "white";
2405 ctx.fill();
2406 if (label == 'L') {
2407 ctx.strokeStyle = "rgba(255,0,0, 1)";
2408 ctx.fillStyle = "rgba(255,0,0, 1)";
2409 } else {
2410 ctx.strokeStyle = "rgba(0,0,255, 1)";
2411 ctx.fillStyle = "rgba(0,0,255, 1)";
2412 }
2413 ctx.stroke();
2414 ctx.font = "normal 16px Arial";
2415 ctx.textAlign = "center";
2416 ctx.fillText(label, _px, _py + 5);
2417 ctx.font = "normal 10px Arial";
2418}
2419
2420function drawID(curve, id) {
2421 var px = x_at_t(curve, 0.5);
2422 var py = y_at_t(curve, 0.5);
2423 var _px = (px - srcLeft) * scale;
2424 var _py = (py - srcTop) * scale;
2425 draw_id_at(id, _px, _py);
2426}
2427
2428function draw_id_at(id, _px, _py) {
2429 ctx.beginPath();
2430 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2431 ctx.closePath();
2432 ctx.fillStyle = "white";
2433 ctx.fill();
2434 ctx.strokeStyle = "rgba(127,127,0, 1)";
2435 ctx.fillStyle = "rgba(127,127,0, 1)";
2436 ctx.stroke();
2437 ctx.font = "normal 16px Arial";
2438 ctx.textAlign = "center";
2439 ctx.fillText(id, _px, _py + 5);
2440 ctx.font = "normal 10px Arial";
2441}
2442
2443function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2444 var curve = [x1, y1, x2, y2];
2445 drawCurvePartialID(id, curve, t1, t2);
2446}
2447
2448function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2449 var curve = [x1, y1, x2, y2, x3, y3];
2450 drawCurvePartialID(id, curve, t1, t2);
2451}
2452
caryclark1049f122015-04-20 08:31:59 -07002453function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2454 var curve = [x1, y1, x2, y2, x3, y3, w];
2455 drawCurvePartialID(id, curve, t1, t2);
2456}
2457
caryclarkdac1d172014-06-17 05:15:38 -07002458function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2459 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2460 drawCurvePartialID(id, curve, t1, t2);
2461}
2462
2463function drawCurvePartialID(id, curve, t1, t2) {
2464 var px = x_at_t(curve, (t1 + t2) / 2);
2465 var py = y_at_t(curve, (t1 + t2) / 2);
2466 var _px = (px - srcLeft) * scale;
2467 var _py = (py - srcTop) * scale;
2468 draw_id_at(id, _px, _py);
2469}
2470
2471function drawCurveSpecials(test, curve, type) {
2472 if (pt_labels) {
2473 drawPoints(curve, type, pt_labels == 2);
2474 }
2475 if (control_lines != 0) {
2476 drawControlLines(curve, type, control_lines);
2477 }
2478 if (curve_t) {
2479 drawPointAtT(curve, type);
2480 }
2481 if (draw_midpoint) {
2482 var mid = pointAtT(curve, type, 0.5);
2483 drawPoint(mid.x, mid.y, true);
2484 }
2485 if (draw_id) {
2486 var id = idByCurve(test, curve, type);
2487 if (id >= 0) {
2488 drawID(curve, id);
2489 }
2490 }
2491 if (type == PATH_LINE) {
2492 return;
2493 }
2494 if (draw_deriviatives > 0) {
2495 var d = dxy_at_t(curve, type, 0);
caryclark03b03ca2015-04-23 09:13:37 -07002496 drawArrow(curve[0], curve[1], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002497 if (draw_deriviatives == 2) {
2498 d = dxy_at_t(curve, type, 1);
2499 if (type == PATH_CUBIC) {
caryclark03b03ca2015-04-23 09:13:37 -07002500 drawArrow(curve[6], curve[7], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002501 } else {
caryclark03b03ca2015-04-23 09:13:37 -07002502 drawArrow(curve[4], curve[5], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002503 }
2504 }
2505 if (draw_midpoint) {
2506 var mid = pointAtT(curve, type, 0.5);
2507 d = dxy_at_t(curve, type, 0.5);
caryclark03b03ca2015-04-23 09:13:37 -07002508 drawArrow(mid.x, mid.y, d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002509 }
2510 }
2511 if (type != PATH_CUBIC) {
2512 return;
2513 }
caryclarkdac1d172014-06-17 05:15:38 -07002514 if (draw_sequence) {
2515 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2516 for (var i = 0; i < 8; i+= 2) {
2517 drawLabelX(ymin, i >> 1, curve[i]);
2518 }
2519 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2520 for (var i = 1; i < 8; i+= 2) {
2521 drawLabelY(xmin, i >> 1, curve[i]);
2522 }
2523 }
2524}
2525
2526function logCurves(test) {
2527 for (curves in test) {
2528 var curve = test[curves];
2529 dumpCurve(curve);
2530 }
2531}
2532
2533function curveToString(curve) {
2534 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002535 var length = curve.length == 7 ? 6 : curve.length;
2536 if (curve.length == 7) {
2537 str += "{";
2538 }
2539 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002540 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2541 if (i < curve.length - 2) {
2542 str += "}, {";
2543 }
2544 }
caryclark1049f122015-04-20 08:31:59 -07002545 str += "}";
2546 if (curve.length == 7) {
2547 str += "}, " + curve[6].toFixed(decimal_places);
2548 }
2549 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07002550 return str;
2551}
2552
2553function dumpCurve(curve) {
2554 console.log(curveToString(curve));
2555}
2556
2557function draw(test, lines, title) {
2558 ctx.fillStyle = "rgba(0,0,0, 0.1)";
2559 ctx.font = "normal 50px Arial";
2560 ctx.textAlign = "left";
2561 ctx.fillText(title, 50, 50);
2562 ctx.font = "normal 10px Arial";
2563 ctx.lineWidth = "1.001"; "0.999";
2564 var secondPath = test.length;
2565 var closeCount = 0;
2566 logStart = -1;
2567 logRange = 0;
2568 // find last active rec type at this step
2569 var curType = test[0];
2570 var curStep = 0;
2571 var hasOp = false;
2572 var lastActive = 0;
2573 var lastAdd = 0;
caryclark624637c2015-05-11 07:21:27 -07002574 var lastCoin = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002575 var lastSect = 0;
2576 var lastSort = 0;
2577 var lastMark = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002578 var lastTop = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002579 activeCount = 0;
2580 addCount = 0;
2581 angleCount = 0;
2582 opCount = 0;
2583 sectCount = 0;
2584 sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002585 topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002586 markCount = 0;
2587 activeMax = 0;
2588 addMax = 0;
2589 angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -07002590 coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002591 opMax = 0;
2592 sectMax = 0;
2593 sectMax2 = 0;
2594 sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002595 topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002596 markMax = 0;
2597 lastIndex = test.length - 3;
2598 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
2599 var recType = test[tIndex];
2600 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
2601 console.log("unknown rec type: " + recType);
2602 throw "stop execution";
2603 }
2604 // if (curType == recType && curType != REC_TYPE_ADD) {
2605 // continue;
2606 // }
2607 var inStepRange = step_limit == 0 || curStep < step_limit;
2608 curType = recType;
2609 if (recType == REC_TYPE_OP) {
2610 hasOp = true;
2611 continue;
2612 }
2613 if (recType == REC_TYPE_UNKNOWN) {
2614 // these types do not advance step
2615 continue;
2616 }
2617 var bumpStep = false;
2618 var records = test[tIndex + 2];
2619 var fragType = records[0];
2620 if (recType == REC_TYPE_ADD) {
2621 if (records.length != 2) {
2622 console.log("expect only two elements: " + records.length);
2623 throw "stop execution";
2624 }
2625 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
2626 continue;
2627 }
2628 ++addMax;
2629 if (!draw_add || !inStepRange) {
2630 continue;
2631 }
2632 lastAdd = tIndex;
2633 ++addCount;
2634 bumpStep = true;
2635 }
2636 if (recType == REC_TYPE_PATH && hasOp) {
2637 secondPath = tIndex;
2638 }
caryclark54359292015-03-26 07:52:43 -07002639 if (recType == REC_TYPE_PATH2 && hasOp) {
2640 secondPath = tIndex;
2641 }
caryclarkdac1d172014-06-17 05:15:38 -07002642 if (recType == REC_TYPE_ACTIVE) {
2643 ++activeMax;
2644 if (!draw_active || !inStepRange) {
2645 continue;
2646 }
2647 lastActive = tIndex;
2648 ++activeCount;
2649 bumpStep = true;
2650 }
2651 if (recType == REC_TYPE_ACTIVE_OP) {
2652 ++opMax;
2653 if (!draw_op || !inStepRange) {
2654 continue;
2655 }
2656 lastOp = tIndex;
2657 ++opCount;
2658 bumpStep = true;
2659 }
caryclark54359292015-03-26 07:52:43 -07002660 if (recType == REC_TYPE_AFTERPART) {
2661 if (draw_angle != 3 || !inStepRange) {
2662 continue;
2663 }
2664 lastAngle = tIndex;
2665 ++angleCount;
2666 bumpStep = true;
2667 }
caryclarkdac1d172014-06-17 05:15:38 -07002668 if (recType == REC_TYPE_ANGLE) {
2669 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07002670 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07002671 continue;
2672 }
2673 lastAngle = tIndex;
2674 ++angleCount;
2675 bumpStep = true;
2676 }
caryclark624637c2015-05-11 07:21:27 -07002677 if (recType == REC_TYPE_COINCIDENCE) {
2678 ++coinMax;
2679 if (!draw_coincidence || !inStepRange) {
2680 continue;
2681 }
2682 lastCoin = tIndex;
2683 ++coinCount;
2684 bumpStep = true;
2685 }
caryclarkdac1d172014-06-17 05:15:38 -07002686 if (recType == REC_TYPE_SECT) {
2687 if (records.length != 2) {
2688 console.log("expect only two elements: " + records.length);
2689 throw "stop execution";
2690 }
2691 ++sectMax;
2692 var sectBump = 1;
2693 switch (fragType) {
2694 case INTERSECT_LINE:
2695 case INTERSECT_QUAD_LINE:
2696 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002697 case INTERSECT_CONIC_LINE:
2698 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07002699 case INTERSECT_SELF_CUBIC:
2700 case INTERSECT_CUBIC_LINE:
2701 case INTERSECT_CUBIC_QUAD:
2702 case INTERSECT_CUBIC:
2703 sectBump = 1;
2704 break;
2705 case INTERSECT_LINE_2:
2706 case INTERSECT_QUAD_LINE_2:
2707 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07002708 case INTERSECT_CONIC_LINE_2:
2709 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07002710 case INTERSECT_CUBIC_LINE_2:
2711 case INTERSECT_CUBIC_QUAD_2:
2712 case INTERSECT_CUBIC_2:
2713 sectBump = 2;
2714 break;
2715 case INTERSECT_LINE_NO:
2716 case INTERSECT_QUAD_LINE_NO:
2717 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07002718 case INTERSECT_CONIC_LINE_NO:
2719 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07002720 case INTERSECT_SELF_CUBIC_NO:
2721 case INTERSECT_CUBIC_LINE_NO:
2722 case INTERSECT_CUBIC_QUAD_NO:
2723 case INTERSECT_CUBIC_NO:
2724 sectBump = 0;
2725 break;
2726 case INTERSECT_CUBIC_LINE_3:
2727 case INTERSECT_CUBIC_QUAD_3:
2728 case INTERSECT_CUBIC_3:
2729 sectBump = 3;
2730 break;
2731 case INTERSECT_CUBIC_QUAD_4:
2732 case INTERSECT_CUBIC_4:
2733 sectBump = 4;
2734 break;
2735 default:
2736 console.log("missing case " + records.length);
2737 throw "stop execution";
2738 }
2739 sectMax2 += sectBump;
2740 if (draw_intersection <= 1 || !inStepRange) {
2741 continue;
2742 }
2743 lastSect = tIndex;
2744 sectCount += sectBump;
2745 bumpStep = true;
2746 }
2747 if (recType == REC_TYPE_SORT) {
2748 ++sortMax;
2749 if (!draw_sort || !inStepRange) {
2750 continue;
2751 }
2752 lastSort = tIndex;
2753 ++sortCount;
2754 bumpStep = true;
2755 }
caryclark03b03ca2015-04-23 09:13:37 -07002756 if (recType == REC_TYPE_TOP) {
2757 ++topMax;
2758 if (!draw_top || !inStepRange) {
2759 continue;
2760 }
2761 lastTop = tIndex;
2762 ++topCount;
2763 bumpStep = true;
2764 }
caryclarkdac1d172014-06-17 05:15:38 -07002765 if (recType == REC_TYPE_MARK) {
2766 ++markMax;
2767 if (!draw_mark || !inStepRange) {
2768 continue;
2769 }
2770 lastMark = tIndex;
2771 ++markCount;
2772 bumpStep = true;
2773 }
2774 if (bumpStep) {
2775 lastIndex = tIndex;
2776 logStart = test[tIndex + 1];
2777 logRange = records.length / 2;
2778 ++curStep;
2779 }
2780 }
2781 stepMax = (draw_add ? addMax : 0)
2782 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07002783 + (draw_angle ? angleMax : 0)
caryclark624637c2015-05-11 07:21:27 -07002784 + (draw_coincidence ? coinMax : 0)
caryclark54359292015-03-26 07:52:43 -07002785 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002786 + (draw_sort ? sortMax : 0)
caryclark03b03ca2015-04-23 09:13:37 -07002787 + (draw_top ? topMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002788 + (draw_mark ? markMax : 0)
2789 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
2790 if (stepMax == 0) {
caryclark624637c2015-05-11 07:21:27 -07002791 stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax;
caryclarkdac1d172014-06-17 05:15:38 -07002792 }
2793 drawnPts = [];
2794 drawnLines = [];
2795 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07002796 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07002797 drawnCubics = [];
2798 focusXmin = focusYmin = Infinity;
2799 focusXmax = focusYmax = -Infinity;
2800 var pathIndex = 0;
2801 var opLetter = 'S';
2802 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
2803 var recType = test[tIndex];
2804 var records = test[tIndex + 2];
2805 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
2806 var fragType = records[recordIndex];
2807 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
2808 console.log("unknown in range frag type: " + fragType);
2809 throw "stop execution";
2810 }
2811 var frags = records[recordIndex + 1];
2812 focus_enabled = false;
2813 switch (recType) {
2814 case REC_TYPE_COMPUTED:
2815 if (draw_computed == 0) {
2816 continue;
2817 }
2818 ctx.lineWidth = 1;
2819 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
2820 ctx.fillStyle = "blue";
2821 var drawThis = false;
2822 switch (fragType) {
2823 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002824 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
2825 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002826 drawQuad(frags[0], frags[1], frags[2], frags[3],
2827 frags[4], frags[5]);
2828 drawThis = true;
2829 }
2830 break;
caryclark1049f122015-04-20 08:31:59 -07002831 case PATH_CONIC:
2832 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
2833 && (draw_computed & 7) == pathIndex)) {
2834 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2835 frags[4], frags[5], frags[6]);
2836 drawThis = true;
2837 }
2838 break;
caryclarkdac1d172014-06-17 05:15:38 -07002839 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07002840 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
2841 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002842 drawCubic(frags[0], frags[1], frags[2], frags[3],
2843 frags[4], frags[5], frags[6], frags[7]);
2844 drawThis = true;
2845 }
2846 ++pathIndex;
2847 break;
2848 case COMPUTED_SET_1:
2849 pathIndex = 0;
2850 break;
2851 case COMPUTED_SET_2:
2852 pathIndex = 1;
2853 break;
2854 default:
2855 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
2856 throw "stop execution";
2857 }
2858 if (!drawThis || collect_bounds) {
2859 break;
2860 }
2861 drawCurveSpecials(test, frags, fragType);
2862 break;
caryclark26ad22a2015-10-16 09:03:38 -07002863 case REC_TYPE_ALIGNED:
2864 if (draw_path < 4) {
2865 continue;
2866 }
caryclarkdac1d172014-06-17 05:15:38 -07002867 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07002868 case REC_TYPE_PATH2:
caryclark26ad22a2015-10-16 09:03:38 -07002869 if (REC_TYPE_ALIGNED != recType && draw_path >= 4) {
2870 continue;
2871 }
caryclarkdac1d172014-06-17 05:15:38 -07002872 if (!draw_path) {
2873 continue;
2874 }
2875 var firstPath = tIndex < secondPath;
2876 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
2877 continue;
2878 }
2879 ctx.lineWidth = 1;
2880 ctx.strokeStyle = firstPath ? "black" : "red";
2881 ctx.fillStyle = "blue";
caryclark54359292015-03-26 07:52:43 -07002882 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07002883 switch (fragType) {
2884 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07002885 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
2886 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07002887 break;
2888 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07002889 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
2890 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
2891 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07002892 break;
caryclark1049f122015-04-20 08:31:59 -07002893 case PATH_CONIC:
2894 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
2895 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
2896 frags2[4], frags2[5], frags2[6]);
2897 break;
caryclarkdac1d172014-06-17 05:15:38 -07002898 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07002899 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
2900 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
2901 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07002902 break;
2903 default:
caryclark26ad22a2015-10-16 09:03:38 -07002904 console.log("unknown " + recType + " frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002905 throw "stop execution";
2906 }
2907 if (collect_bounds) {
2908 break;
2909 }
caryclark54359292015-03-26 07:52:43 -07002910 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002911 break;
2912 case REC_TYPE_OP:
2913 switch (fragType) {
2914 case OP_INTERSECT: opLetter = 'I'; break;
2915 case OP_DIFFERENCE: opLetter = 'D'; break;
2916 case OP_UNION: opLetter = 'U'; break;
2917 case OP_XOR: opLetter = 'X'; break;
2918 default:
2919 console.log("unknown REC_TYPE_OP frag type: " + fragType);
2920 throw "stop execution";
2921 }
2922 break;
2923 case REC_TYPE_ACTIVE:
2924 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
2925 continue;
2926 }
2927 var x1 = frags[SPAN_X1];
2928 var y1 = frags[SPAN_Y1];
2929 var x2 = frags[SPAN_X2];
2930 var y2 = frags[SPAN_Y2];
caryclark1049f122015-04-20 08:31:59 -07002931 var x3, y3, x3, y4, t1, t2, w;
caryclarkdac1d172014-06-17 05:15:38 -07002932 ctx.lineWidth = 3;
2933 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2934 focus_enabled = true;
2935 switch (fragType) {
2936 case ACTIVE_LINE_SPAN:
2937 t1 = frags[SPAN_L_T];
2938 t2 = frags[SPAN_L_TEND];
2939 drawLinePartial(x1, y1, x2, y2, t1, t2);
2940 if (draw_id) {
2941 drawLinePartialID(frags[0], x1, y1, x2, y2, t1, t2);
2942 }
2943 break;
2944 case ACTIVE_QUAD_SPAN:
2945 x3 = frags[SPAN_X3];
2946 y3 = frags[SPAN_Y3];
2947 t1 = frags[SPAN_Q_T];
2948 t2 = frags[SPAN_Q_TEND];
2949 drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2950 if (draw_id) {
2951 drawQuadPartialID(frags[0], x1, y1, x2, y2, x3, y3, t1, t2);
2952 }
2953 break;
caryclark1049f122015-04-20 08:31:59 -07002954 case ACTIVE_CONIC_SPAN:
2955 x3 = frags[SPAN_X3];
2956 y3 = frags[SPAN_Y3];
2957 t1 = frags[SPAN_K_T];
2958 t2 = frags[SPAN_K_TEND];
2959 w = frags[SPAN_K_W];
2960 drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2961 if (draw_id) {
2962 drawConicPartialID(frags[0], x1, y1, x2, y2, x3, y3, w, t1, t2);
2963 }
2964 break;
caryclarkdac1d172014-06-17 05:15:38 -07002965 case ACTIVE_CUBIC_SPAN:
2966 x3 = frags[SPAN_X3];
2967 y3 = frags[SPAN_Y3];
2968 x4 = frags[SPAN_X4];
2969 y4 = frags[SPAN_Y4];
2970 t1 = frags[SPAN_C_T];
2971 t2 = frags[SPAN_C_TEND];
2972 drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2973 if (draw_id) {
2974 drawCubicPartialID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2975 }
2976 break;
2977 default:
2978 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
2979 throw "stop execution";
2980 }
2981 break;
2982 case REC_TYPE_ACTIVE_OP:
2983 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
2984 continue;
2985 }
2986 focus_enabled = true;
2987 ctx.lineWidth = 3;
2988 var activeSpan = frags[7] == "1";
2989 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
2990 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
2991 drawCurve(curve);
2992 if (draw_op > 1) {
2993 drawArc(curve, false, frags[3], frags[4]);
2994 drawArc(curve, true, frags[5], frags[6]);
2995 }
2996 break;
2997 case REC_TYPE_ADD:
2998 if (!draw_add) {
2999 continue;
3000 }
3001 ctx.lineWidth = 3;
3002 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
3003 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
3004 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
3005 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
3006 : "rgba(127,0,127, 0.3)";
3007 focus_enabled = true;
3008 switch (fragType) {
3009 case ADD_MOVETO:
3010 break;
3011 case ADD_LINETO:
3012 if (step_limit == 0 || tIndex >= lastAdd) {
3013 drawLine(frags[0], frags[1], frags[2], frags[3]);
3014 }
3015 break;
3016 case ADD_QUADTO:
3017 if (step_limit == 0 || tIndex >= lastAdd) {
3018 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
3019 }
3020 break;
caryclark1049f122015-04-20 08:31:59 -07003021 case ADD_CONICTO:
3022 if (step_limit == 0 || tIndex >= lastAdd) {
3023 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3024 frags[4], frags[5], frags[6]);
3025 }
3026 break;
caryclarkdac1d172014-06-17 05:15:38 -07003027 case ADD_CUBICTO:
3028 if (step_limit == 0 || tIndex >= lastAdd) {
3029 drawCubic(frags[0], frags[1], frags[2], frags[3],
3030 frags[4], frags[5], frags[6], frags[7]);
3031 }
3032 break;
3033 case ADD_CLOSE:
3034 ++closeCount;
3035 break;
3036 case ADD_FILL:
3037 break;
3038 default:
3039 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
3040 throw "stop execution";
3041 }
3042 break;
3043 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07003044 angleBetween = frags[18] == "T";
3045 afterIndex = 0;
3046 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07003047 continue;
3048 }
3049 focus_enabled = true;
3050 ctx.lineWidth = 3;
3051 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07003052 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
3053 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
3054 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07003055 drawCurve(leftCurve);
3056 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07003057 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07003058 drawCurve(midCurve);
3059 if (draw_angle > 1) {
3060 drawOrder(leftCurve, 'L');
3061 drawOrder(rightCurve, 'R');
3062 }
3063 break;
caryclark54359292015-03-26 07:52:43 -07003064 case REC_TYPE_AFTERPART:
3065 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
3066 continue;
3067 }
3068 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
3069 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
3070 : "rgba(0,0,255, 1.0)";
3071 switch (fragType) {
3072 case PATH_LINE:
3073 drawLine(frags[0], frags[1], frags[2], frags[3]);
3074 break;
3075 case PATH_QUAD:
3076 drawQuad(frags[0], frags[1], frags[2], frags[3],
3077 frags[4], frags[5]);
3078 break;
caryclark1049f122015-04-20 08:31:59 -07003079 case PATH_CONIC:
3080 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3081 frags[4], frags[5], frags[6]);
3082 break;
caryclark54359292015-03-26 07:52:43 -07003083 case PATH_CUBIC:
3084 drawCubic(frags[0], frags[1], frags[2], frags[3],
caryclark1049f122015-04-20 08:31:59 -07003085 frags[4], frags[5], frags[6], frags[7]);
caryclark54359292015-03-26 07:52:43 -07003086 break;
3087 default:
3088 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
3089 throw "stop execution";
3090 }
3091 ++afterIndex;
3092 break;
caryclark624637c2015-05-11 07:21:27 -07003093 case REC_TYPE_COINCIDENCE:
3094 if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) {
3095 continue;
3096 }
3097 focus_enabled = true;
3098 ctx.lineWidth = 3;
3099 ctx.strokeStyle = "rgba(127,45,63, 0.3)";
3100 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3101 drawCurve(curve);
3102 break;
caryclarkdac1d172014-06-17 05:15:38 -07003103 case REC_TYPE_SECT:
3104 if (!draw_intersection) {
3105 continue;
3106 }
3107 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
3108 continue;
3109 }
3110 // draw_intersection == 1 : show all
3111 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
3112 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
3113 ctx.lineWidth = 1;
3114 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3115 ctx.fillStyle = "blue";
3116 focus_enabled = true;
3117 var f = [];
3118 var c1s;
3119 var c1l;
3120 var c2s;
3121 var c2l;
3122 switch (fragType) {
3123 case INTERSECT_LINE:
3124 f.push(5, 6, 0, 7);
3125 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
3126 break;
3127 case INTERSECT_LINE_2:
3128 f.push(5, 6, 0, 10);
3129 f.push(8, 9, 7, 15);
3130 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
3131 break;
3132 case INTERSECT_LINE_NO:
3133 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
3134 break;
3135 case INTERSECT_QUAD_LINE:
3136 f.push(7, 8, 0, 9);
3137 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
3138 break;
3139 case INTERSECT_QUAD_LINE_2:
3140 f.push(7, 8, 0, 12);
3141 f.push(10, 11, 9, 17);
3142 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
3143 break;
3144 case INTERSECT_QUAD_LINE_NO:
3145 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
3146 break;
3147 case INTERSECT_QUAD:
3148 f.push(7, 8, 0, 9);
3149 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
3150 break;
3151 case INTERSECT_QUAD_2:
3152 f.push(7, 8, 0, 12);
3153 f.push(10, 11, 9, 19);
3154 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
3155 break;
3156 case INTERSECT_QUAD_NO:
3157 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
3158 break;
caryclark1049f122015-04-20 08:31:59 -07003159 case INTERSECT_CONIC_LINE:
3160 f.push(8, 9, 0, 10);
3161 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
3162 break;
3163 case INTERSECT_CONIC_LINE_2:
3164 f.push(8, 9, 0, 12);
3165 f.push(11, 12, 10, 18);
3166 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
3167 break;
3168 case INTERSECT_CONIC_LINE_NO:
3169 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
3170 break;
3171 case INTERSECT_CONIC:
3172 f.push(8, 9, 0, 10);
3173 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
3174 break;
3175 case INTERSECT_CONIC_2:
3176 f.push(8, 9, 0, 13);
3177 f.push(11, 12, 10, 21);
3178 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
3179 break;
3180 case INTERSECT_CONIC_NO:
3181 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
3182 break;
caryclarkdac1d172014-06-17 05:15:38 -07003183 case INTERSECT_SELF_CUBIC:
3184 f.push(9, 10, 0, 11);
3185 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
3186 break;
3187 case INTERSECT_SELF_CUBIC_NO:
3188 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
3189 break;
3190 case INTERSECT_CUBIC_LINE:
3191 f.push(9, 10, 0, 11);
3192 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3193 break;
3194 case INTERSECT_CUBIC_LINE_2:
3195 f.push(9, 10, 0, 14);
3196 f.push(12, 13, 11, 19);
3197 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3198 break;
3199 case INTERSECT_CUBIC_LINE_3:
3200 f.push(9, 10, 0, 17);
3201 f.push(12, 13, 11, 22);
3202 f.push(15, 16, 14, 23);
3203 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3204 break;
3205 case INTERSECT_CUBIC_QUAD_NO:
3206 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3207 break;
3208 case INTERSECT_CUBIC_QUAD:
3209 f.push(9, 10, 0, 11);
3210 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3211 break;
3212 case INTERSECT_CUBIC_QUAD_2:
3213 f.push(9, 10, 0, 14);
3214 f.push(12, 13, 11, 21);
3215 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3216 break;
3217 case INTERSECT_CUBIC_QUAD_3:
3218 f.push(9, 10, 0, 17);
3219 f.push(12, 13, 11, 24);
3220 f.push(15, 16, 14, 25);
3221 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3222 break;
3223 case INTERSECT_CUBIC_QUAD_4:
3224 f.push(9, 10, 0, 20);
3225 f.push(12, 13, 11, 27);
3226 f.push(15, 16, 14, 28);
3227 f.push(18, 19, 17, 29);
3228 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3229 break;
3230 case INTERSECT_CUBIC_LINE_NO:
3231 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3232 break;
3233 case INTERSECT_CUBIC:
3234 f.push(9, 10, 0, 11);
3235 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3236 break;
3237 case INTERSECT_CUBIC_2:
3238 f.push(9, 10, 0, 14);
3239 f.push(12, 13, 11, 23);
3240 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3241 break;
3242 case INTERSECT_CUBIC_3:
3243 f.push(9, 10, 0, 17);
3244 f.push(12, 13, 11, 26);
3245 f.push(15, 16, 14, 27);
3246 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3247 break;
3248 case INTERSECT_CUBIC_4:
3249 f.push(9, 10, 0, 20);
3250 f.push(12, 13, 11, 29);
3251 f.push(15, 16, 14, 30);
3252 f.push(18, 19, 17, 31);
3253 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3254 break;
3255 case INTERSECT_CUBIC_NO:
3256 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3257 break;
3258 default:
3259 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3260 throw "stop execution";
3261 }
3262 if (draw_intersection != 1) {
3263 var id = -1;
3264 var curve;
3265 switch (c1l) {
3266 case 4:
3267 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3268 if (draw_id) {
3269 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3270 id = idByCurve(test, curve, PATH_LINE);
3271 }
3272 break;
3273 case 6:
3274 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3275 frags[c1s + 4], frags[c1s + 5]);
3276 if (draw_id) {
3277 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3278 frags[c1s + 4], frags[c1s + 5]];
3279 id = idByCurve(test, curve, PATH_QUAD);
3280 }
3281 break;
caryclark1049f122015-04-20 08:31:59 -07003282 case 7:
3283 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3284 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3285 if (draw_id) {
3286 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3287 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3288 id = idByCurve(test, curve, PATH_CONIC);
3289 }
3290 break;
caryclarkdac1d172014-06-17 05:15:38 -07003291 case 8:
3292 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3293 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3294 if (draw_id) {
3295 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3296 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3297 id = idByCurve(test, curve, PATH_CUBIC);
3298 }
3299 break;
3300 }
3301 if (id >= 0) {
3302 drawID(curve, id);
3303 }
3304 id = -1;
3305 switch (c2l) {
3306 case 0:
3307 break;
3308 case 4:
3309 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3310 if (draw_id) {
3311 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3312 id = idByCurve(test, curve, PATH_LINE);
3313 }
3314 break;
3315 case 6:
3316 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3317 frags[c2s + 4], frags[c2s + 5]);
3318 if (draw_id) {
3319 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3320 frags[c2s + 4], frags[c2s + 5]];
3321 id = idByCurve(test, curve, PATH_QUAD);
3322 }
3323 break;
caryclark1049f122015-04-20 08:31:59 -07003324 case 7:
3325 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3326 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3327 if (draw_id) {
3328 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3329 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3330 id = idByCurve(test, curve, PATH_CONIC);
3331 }
3332 break;
caryclarkdac1d172014-06-17 05:15:38 -07003333 case 8:
3334 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3335 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3336 if (draw_id) {
3337 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3338 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3339 id = idByCurve(test, curve, PATH_CUBIC);
3340 }
3341 break;
3342 }
3343 if (id >= 0) {
3344 drawID(curve, id);
3345 }
3346 }
3347 if (collect_bounds) {
3348 break;
3349 }
caryclark54359292015-03-26 07:52:43 -07003350 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3351 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003352 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3353 }
3354 }
3355 if (!draw_intersectT) {
3356 break;
3357 }
3358 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003359 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3360 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003361 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3362 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3363 }
3364 }
3365 break;
3366 case REC_TYPE_SORT:
3367 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3368 continue;
3369 }
3370 ctx.lineWidth = 3;
3371 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3372 focus_enabled = true;
3373 switch (fragType) {
3374 case SORT_UNARY:
3375 case SORT_BINARY:
3376 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3377 drawCurve(curve);
3378 break;
3379 default:
3380 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3381 throw "stop execution";
3382 }
3383 break;
caryclark03b03ca2015-04-23 09:13:37 -07003384 case REC_TYPE_TOP:
3385 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
3386 continue;
3387 }
3388 ctx.lineWidth = 3;
3389 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3390 focus_enabled = true;
3391 {
3392 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3393 drawCurve(curve);
3394 var type = PATH_LINE + (curve.length / 2 - 2);
3395 var mid = pointAtT(curve, type, 0.5);
3396 var d = dxy_at_t(curve, type, 0.5);
3397 drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
3398 }
3399 break;
caryclarkdac1d172014-06-17 05:15:38 -07003400 case REC_TYPE_MARK:
3401 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3402 continue;
3403 }
3404 ctx.lineWidth = 3;
3405 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3406 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3407 focus_enabled = true;
3408 switch (fragType) {
3409 case MARK_LINE:
3410 case MARK_DONE_LINE:
3411 case MARK_UNSORTABLE_LINE:
3412 case MARK_SIMPLE_LINE:
3413 case MARK_SIMPLE_DONE_LINE:
3414 case MARK_DONE_UNARY_LINE:
3415 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3416 frags[5], frags[9]);
3417 if (draw_id) {
3418 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3419 frags[5], frags[9]);
3420 }
3421 break;
3422 case MARK_QUAD:
3423 case MARK_DONE_QUAD:
3424 case MARK_UNSORTABLE_QUAD:
3425 case MARK_SIMPLE_QUAD:
3426 case MARK_SIMPLE_DONE_QUAD:
3427 case MARK_DONE_UNARY_QUAD:
3428 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3429 frags[5], frags[6], frags[7], frags[11]);
3430 if (draw_id) {
3431 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3432 frags[5], frags[6], frags[7], frags[11]);
3433 }
3434 break;
3435 case MARK_CUBIC:
3436 case MARK_DONE_CUBIC:
3437 case MARK_UNSORTABLE_CUBIC:
3438 case MARK_SIMPLE_CUBIC:
3439 case MARK_SIMPLE_DONE_CUBIC:
3440 case MARK_DONE_UNARY_CUBIC:
3441 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3442 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3443 if (draw_id) {
3444 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3445 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3446 }
3447 break;
3448 case MARK_ANGLE_LAST:
3449 // FIXME: ignored for now
3450 break;
3451 default:
3452 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3453 throw "stop execution";
3454 }
3455 break;
3456 default:
3457 continue;
3458 }
3459 }
3460 switch (recType) {
3461 case REC_TYPE_SORT:
3462 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3463 break;
3464 }
3465 var angles = []; // use tangent lines to describe arcs
3466 var windFrom = [];
3467 var windTo = [];
3468 var opp = [];
3469 var minXY = Number.MAX_VALUE;
3470 var partial;
3471 focus_enabled = true;
3472 var someUnsortable = false;
3473 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3474 var fragType = records[recordIndex];
3475 var frags = records[recordIndex + 1];
3476 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3477 (fragType == SORT_BINARY && frags[16]);
3478 someUnsortable |= unsortable;
3479 switch (fragType) {
3480 case SORT_UNARY:
3481 case SORT_BINARY:
3482 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3483 break;
3484 default:
3485 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3486 throw "stop execution";
3487 }
3488 var dx = boundsWidth(partial);
3489 var dy = boundsHeight(partial);
3490 minXY = Math.min(minXY, dx * dx + dy * dy);
3491 if (collect_bounds) {
3492 continue;
3493 }
3494 angles.push(tangent(partial));
3495 var from = frags[12];
3496 var to = frags[12];
3497 var sgn = frags[10];
3498 if (sgn < 0) {
3499 from -= frags[11];
3500 } else if (sgn > 0) {
3501 to -= frags[11];
3502 }
3503 windFrom.push(from + (unsortable ? "!" : ""));
3504 windTo.push(to + (unsortable ? "!" : ""));
3505 opp.push(fragType == SORT_BINARY);
3506 if (draw_sort == 1) {
3507 drawOrder(partial, frags[12]);
3508 } else {
3509 drawOrder(partial, (recordIndex / 2) + 1);
3510 }
3511 }
3512 var radius = Math.sqrt(minXY) / 2 * scale;
3513 radius = Math.min(50, radius);
3514 var scaledRadius = radius / scale;
3515 var centerX = partial[0];
3516 var centerY = partial[1];
3517 if (collect_bounds) {
3518 if (focus_enabled) {
3519 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
3520 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
3521 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
3522 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
3523 }
3524 break;
3525 }
3526 break;
3527 default:
3528 break;
3529 }
3530 }
3531 if (collect_bounds) {
3532 return;
3533 }
3534 if (draw_log && logStart >= 0) {
3535 ctx.font = "normal 10px Arial";
3536 ctx.textAlign = "left";
3537 ctx.beginPath();
3538 var top = screenHeight - 20 - (logRange + 2) * 10;
3539 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
3540 ctx.fillStyle = "white";
3541 ctx.fill();
3542 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3543 if (logStart > 0) {
3544 ctx.fillText(lines[logStart - 1], 50, top + 8);
3545 }
3546 ctx.fillStyle = "black";
3547 for (var idx = 0; idx < logRange; ++idx) {
3548 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
3549 }
3550 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3551 if (logStart + logRange < lines.length) {
3552 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
3553 }
3554 }
3555 if (draw_legend) {
3556 var pos = 0;
caryclark624637c2015-05-11 07:21:27 -07003557 var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07003558 // drawBox(pos++, "yellow", "black", opLetter, true, '');
3559 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
3560 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
3561 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
3562 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
caryclark624637c2015-05-11 07:21:27 -07003563 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey);
caryclarkdac1d172014-06-17 05:15:38 -07003564 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
3565 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
caryclark03b03ca2015-04-23 09:13:37 -07003566 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
caryclarkdac1d172014-06-17 05:15:38 -07003567 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
3568 drawBox(pos++, "black", "white",
caryclark26ad22a2015-10-16 09:03:38 -07003569 (new Array('P', 'P1', 'P2', 'P', 'p', 'p1', 'p2'))[draw_path], draw_path != 0, pathKey);
caryclarkdac1d172014-06-17 05:15:38 -07003570 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
3571 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
3572 draw_computed != 0, computedKey);
3573 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
3574 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
3575 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
3576 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
3577 if (curve_t) {
3578 drawCurveTControl();
3579 }
3580 ctx.font = "normal 20px Arial";
3581 ctx.fillStyle = "rgba(0,0,0, 0.3)";
3582 ctx.textAlign = "right";
3583 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
3584 }
3585 if (draw_hints) {
3586 ctx.font = "normal 10px Arial";
3587 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3588 ctx.textAlign = "right";
3589 var y = 4;
3590 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
3591 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
3592 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
3593 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07003594 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
3595 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
3596 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
3597 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
3598 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
3599 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
3600 }
3601}
3602
3603function drawBox(y, backC, foreC, str, enable, label) {
3604 ctx.beginPath();
3605 ctx.fillStyle = backC;
3606 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
3607 ctx.fill();
3608 ctx.font = "normal 16px Arial";
3609 ctx.fillStyle = foreC;
3610 ctx.textAlign = "center";
3611 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
3612 if (!enable) {
3613 ctx.fillStyle = "rgba(255,255,255, 0.5)";
3614 ctx.fill();
3615 }
3616 if (label != '') {
3617 ctx.font = "normal 9px Arial";
3618 ctx.fillStyle = "black";
3619 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
3620 }
3621}
3622
3623function drawCurveTControl() {
3624 ctx.lineWidth = 2;
3625 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
3626 ctx.beginPath();
3627 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
3628 ctx.stroke();
3629 var ty = 40 + curveT * (screenHeight - 80);
3630 ctx.beginPath();
3631 ctx.moveTo(screenWidth - 80, ty);
3632 ctx.lineTo(screenWidth - 85, ty - 5);
3633 ctx.lineTo(screenWidth - 85, ty + 5);
3634 ctx.lineTo(screenWidth - 80, ty);
3635 ctx.fillStyle = "rgba(0,0,0, 0.6)";
3636 ctx.fill();
3637 var num = curveT.toFixed(decimal_places);
3638 ctx.font = "normal 10px Arial";
3639 ctx.textAlign = "left";
3640 ctx.fillText(num, screenWidth - 78, ty);
3641}
3642
3643function ptInTControl() {
3644 var e = window.event;
3645 var tgt = e.target || e.srcElement;
3646 var left = tgt.offsetLeft;
3647 var top = tgt.offsetTop;
3648 var x = (e.clientX - left);
3649 var y = (e.clientY - top);
3650 if (x < screenWidth - 80 || x > screenWidth - 50) {
3651 return false;
3652 }
3653 if (y < 40 || y > screenHeight - 80) {
3654 return false;
3655 }
3656 curveT = (y - 40) / (screenHeight - 120);
3657 if (curveT < 0 || curveT > 1) {
3658 throw "stop execution";
3659 }
3660 return true;
3661}
3662
3663function drawTop() {
3664 if (tests[testIndex] == null) {
3665 var str = testDivs[testIndex].textContent;
3666 parse_all(str);
3667 var title = testDivs[testIndex].id.toString();
3668 testTitles[testIndex] = title;
3669 }
3670 init(tests[testIndex]);
3671 redraw();
3672}
3673
3674function redraw() {
3675 if (focus_on_selection) {
3676 collect_bounds = true;
3677 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3678 collect_bounds = false;
3679 if (focusXmin < focusXmax && focusYmin < focusYmax) {
3680 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
3681 }
3682 }
3683 ctx.beginPath();
3684 ctx.fillStyle = "white";
3685 ctx.rect(0, 0, screenWidth, screenHeight);
3686 ctx.fill();
3687 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3688}
3689
3690function dumpCurvePartial(test, id, t0, t1) {
3691 var curve = curveByID(test, id);
3692 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
3693 console.log("id=" + id + " " + name + "=" + curveToString(curve)
3694 + " t0=" + t0 + " t1=" + t1
3695 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
3696}
3697
3698function dumpAngleTest(test, id, t0, t1) {
3699 var curve = curveByID(test, id);
3700 console.log(" { {" + curveToString(curve) + "}, "
3701 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
3702}
3703
3704function dumpLogToConsole() {
3705 if (logStart < 0) {
3706 return;
3707 }
3708 var test = tests[testIndex];
3709 var recType = REC_TYPE_UNKNOWN;
3710 var records;
3711 for (var index = 0; index < test.length; index += 3) {
3712 var lastLineNo = test[index + 1];
3713 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
3714 recType = test[index];
3715 records = test[index + 2];
3716 break;
3717 }
3718 }
3719 if (recType == REC_TYPE_UNKNOWN) {
3720 return;
3721 }
3722 var lines = testLines[testIndex];
3723 for (var idx = 0; idx < logRange; ++idx) {
3724 var line = lines[logStart + idx];
3725 console.log(line);
3726 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3727 var fragType = records[recordIndex];
3728 var frags = records[recordIndex + 1];
3729 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07003730 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
3731 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
3732 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
3733 console.log("\nstatic IntersectData intersectDataSet[] = { //");
3734 dumpAngleTest(test, frags[0], frags[4], frags[5]);
3735 dumpAngleTest(test, frags[6], frags[10], frags[11]);
3736 dumpAngleTest(test, frags[12], frags[16], frags[17]);
3737 console.log("}; //");
3738 }
3739 }
3740 }
3741}
3742
3743var activeKey = 'a';
3744var pathKey = 'b';
3745var pathBackKey = 'B';
3746var centerKey = 'c';
caryclark624637c2015-05-11 07:21:27 -07003747var coincidenceKey = 'C';
caryclarkdac1d172014-06-17 05:15:38 -07003748var addKey = 'd';
3749var deriviativesKey = 'f';
3750var angleKey = 'g';
3751var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07003752var intersectionKey = 'i';
3753var intersectionBackKey = 'I';
3754var sequenceKey = 'j';
3755var midpointKey = 'k';
3756var logKey = 'l';
3757var logToConsoleKey = 'L';
3758var markKey = 'm';
3759var sortKey = 'o';
3760var opKey = 'p';
3761var opBackKey = 'P';
3762var computedKey = 'q';
3763var computedBackKey = 'Q';
3764var stepKey = 's';
3765var stepBackKey = 'S';
3766var intersectTKey = 't';
caryclark03b03ca2015-04-23 09:13:37 -07003767var topKey = 'T';
caryclarkdac1d172014-06-17 05:15:38 -07003768var curveTKey = 'u';
3769var controlLinesBackKey = 'V';
3770var controlLinesKey = 'v';
3771var ptsKey = 'x';
3772var xyKey = 'y';
3773var logCurvesKey = 'z';
3774var focusKey = '`';
3775var idKey = '.';
3776var retinaKey = '\\';
3777
3778function doKeyPress(evt) {
3779 var char = String.fromCharCode(evt.charCode);
3780 var focusWasOn = false;
3781 switch (char) {
3782 case '0':
3783 case '1':
3784 case '2':
3785 case '3':
3786 case '4':
3787 case '5':
3788 case '6':
3789 case '7':
3790 case '8':
3791 case '9':
3792 decimal_places = char - '0';
3793 redraw();
3794 break;
3795 case activeKey:
3796 draw_active ^= true;
3797 redraw();
3798 break;
3799 case addKey:
3800 draw_add ^= true;
3801 redraw();
3802 break;
3803 case angleKey:
caryclark54359292015-03-26 07:52:43 -07003804 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07003805 redraw();
3806 break;
3807 case angleBackKey:
3808 draw_angle = (draw_angle + 2) % 3;
3809 redraw();
3810 break;
3811 case centerKey:
3812 setScale(xmin, xmax, ymin, ymax);
3813 redraw();
3814 break;
caryclark624637c2015-05-11 07:21:27 -07003815 case coincidenceKey:
3816 draw_coincidence ^= true;
3817 redraw();
3818 break;
caryclarkdac1d172014-06-17 05:15:38 -07003819 case controlLinesBackKey:
3820 control_lines = (control_lines + 3) % 4;
3821 redraw();
3822 break;
3823 case controlLinesKey:
3824 control_lines = (control_lines + 1) % 4;
3825 redraw();
3826 break;
3827 case computedBackKey:
3828 draw_computed = (draw_computed + 5) % 6;
3829 redraw();
3830 break;
3831 case computedKey:
3832 draw_computed = (draw_computed + 1) % 6;
3833 redraw();
3834 break;
3835 case curveTKey:
3836 curve_t ^= true;
3837 if (curve_t) {
3838 draw_legend = true;
3839 }
3840 redraw();
3841 break;
3842 case deriviativesKey:
3843 draw_deriviatives = (draw_deriviatives + 1) % 3;
3844 redraw();
3845 break;
3846 case focusKey:
3847 focus_on_selection ^= true;
3848 setScale(xmin, xmax, ymin, ymax);
3849 redraw();
3850 break;
caryclarkdac1d172014-06-17 05:15:38 -07003851 case idKey:
3852 draw_id ^= true;
3853 redraw();
3854 break;
3855 case intersectionBackKey:
3856 draw_intersection = (draw_intersection + 3) % 4;
3857 redraw();
3858 break;
3859 case intersectionKey:
3860 draw_intersection = (draw_intersection + 1) % 4;
3861 redraw();
3862 break;
3863 case intersectTKey:
3864 draw_intersectT ^= true;
3865 redraw();
3866 break;
3867 case logCurvesKey:
3868 logCurves(tests[testIndex]);
3869 break;
3870 case logKey:
3871 draw_log ^= true;
3872 redraw();
3873 break;
3874 case logToConsoleKey:
3875 if (draw_log) {
3876 dumpLogToConsole();
3877 }
3878 break;
3879 case markKey:
3880 draw_mark ^= true;
3881 redraw();
3882 break;
3883 case midpointKey:
3884 draw_midpoint ^= true;
3885 redraw();
3886 break;
3887 case opKey:
3888 draw_op = (draw_op + 1) % 3;
3889 redraw();
3890 break;
3891 case opBackKey:
3892 draw_op = (draw_op + 2) % 3;
3893 redraw();
3894 break;
3895 case pathKey:
caryclark26ad22a2015-10-16 09:03:38 -07003896 draw_path = (draw_path + 1) % (4 + (hasAlignedPath ? 3 : 0));
caryclarkdac1d172014-06-17 05:15:38 -07003897 redraw();
3898 break;
3899 case pathBackKey:
caryclark26ad22a2015-10-16 09:03:38 -07003900 draw_path = (draw_path + 3 + (hasAlignedPath ? 3 : 0)) % (4 + (hasAlignedPath ? 3 : 0));
caryclarkdac1d172014-06-17 05:15:38 -07003901 redraw();
3902 break;
3903 case ptsKey:
3904 pt_labels = (pt_labels + 1) % 3;
3905 redraw();
3906 break;
3907 case retinaKey:
3908 retina_scale ^= true;
3909 drawTop();
3910 break;
3911 case sequenceKey:
3912 draw_sequence ^= true;
3913 redraw();
3914 break;
3915 case sortKey:
3916 draw_sort = (draw_sort + 1) % 3;
3917 drawTop();
3918 break;
3919 case stepKey:
3920 step_limit++;
3921 if (step_limit > stepMax) {
3922 step_limit = stepMax;
3923 }
3924 redraw();
3925 break;
3926 case stepBackKey:
3927 step_limit--;
3928 if (step_limit < 0) {
3929 step_limit = 0;
3930 }
3931 redraw();
3932 break;
caryclark03b03ca2015-04-23 09:13:37 -07003933 case topKey:
3934 draw_top ^= true;
3935 redraw();
3936 break;
caryclarkdac1d172014-06-17 05:15:38 -07003937 case xyKey:
3938 debug_xy = (debug_xy + 1) % 3;
3939 redraw();
3940 break;
3941 case '-':
3942 focusWasOn = focus_on_selection;
3943 if (focusWasOn) {
3944 focus_on_selection = false;
3945 scale /= 1.2;
3946 } else {
3947 scale /= 2;
3948 calcLeftTop();
3949 }
3950 redraw();
3951 focus_on_selection = focusWasOn;
3952 break;
3953 case '=':
3954 case '+':
3955 focusWasOn = focus_on_selection;
3956 if (focusWasOn) {
3957 focus_on_selection = false;
3958 scale *= 1.2;
3959 } else {
3960 scale *= 2;
3961 calcLeftTop();
3962 }
3963 redraw();
3964 focus_on_selection = focusWasOn;
3965 break;
3966 case '?':
3967 draw_hints ^= true;
3968 if (draw_hints && !draw_legend) {
3969 draw_legend = true;
3970 }
3971 redraw();
3972 break;
3973 case '/':
3974 draw_legend ^= true;
3975 redraw();
3976 break;
3977 }
3978}
3979
3980function doKeyDown(evt) {
3981 var char = evt.keyCode;
3982 var preventDefault = false;
3983 switch (char) {
3984 case 37: // left arrow
3985 if (evt.shiftKey) {
3986 testIndex -= 9;
3987 }
3988 if (--testIndex < 0)
3989 testIndex = tests.length - 1;
3990 drawTop();
3991 preventDefault = true;
3992 break;
3993 case 39: // right arrow
3994 if (evt.shiftKey) {
3995 testIndex += 9;
3996 }
3997 if (++testIndex >= tests.length)
3998 testIndex = 0;
3999 drawTop();
4000 preventDefault = true;
4001 break;
4002 }
4003 if (preventDefault) {
4004 evt.preventDefault();
4005 return false;
4006 }
4007 return true;
4008}
4009
4010(function() {
4011 var hidden = "hidden";
4012
4013 // Standards:
4014 if (hidden in document)
4015 document.addEventListener("visibilitychange", onchange);
4016 else if ((hidden = "mozHidden") in document)
4017 document.addEventListener("mozvisibilitychange", onchange);
4018 else if ((hidden = "webkitHidden") in document)
4019 document.addEventListener("webkitvisibilitychange", onchange);
4020 else if ((hidden = "msHidden") in document)
4021 document.addEventListener("msvisibilitychange", onchange);
4022 // IE 9 and lower:
4023 else if ('onfocusin' in document)
4024 document.onfocusin = document.onfocusout = onchange;
4025 // All others:
4026 else
4027 window.onpageshow = window.onpagehide
4028 = window.onfocus = window.onblur = onchange;
4029
4030 function onchange (evt) {
4031 var v = 'visible', h = 'hidden',
4032 evtMap = {
4033 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
4034 };
4035
4036 evt = evt || window.event;
4037 if (evt.type in evtMap)
4038 document.body.className = evtMap[evt.type];
4039 else
4040 document.body.className = this[hidden] ? "hidden" : "visible";
4041 }
4042})();
4043
4044function calcXY() {
4045 var e = window.event;
4046 var tgt = e.target || e.srcElement;
4047 var left = tgt.offsetLeft;
4048 var top = tgt.offsetTop;
4049 mouseX = (e.clientX - left) / scale + srcLeft;
4050 mouseY = (e.clientY - top) / scale + srcTop;
4051}
4052
4053function calcLeftTop() {
4054 srcLeft = mouseX - screenWidth / 2 / scale;
4055 srcTop = mouseY - screenHeight / 2 / scale;
4056}
4057
4058var disableClick = false;
4059
4060function handleMouseClick() {
4061 if (disableClick) {
4062 return;
4063 }
4064 if (!curve_t || !ptInTControl()) {
4065 calcXY();
4066 calcLeftTop();
4067 }
4068 redraw();
4069// if (!curve_t || !ptInTControl()) {
4070// mouseX = screenWidth / 2 / scale + srcLeft;
4071// mouseY = screenHeight / 2 / scale + srcTop;
4072// }
4073}
4074
4075function handleMouseOver() {
4076 calcXY();
4077 if (debug_xy != 2) {
4078 return;
4079 }
4080 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
4081 ctx.beginPath();
4082 ctx.rect(300,100,num.length * 6,10);
4083 ctx.fillStyle="white";
4084 ctx.fill();
4085 ctx.font = "normal 10px Arial";
4086 ctx.fillStyle="black";
4087 ctx.textAlign = "left";
4088 ctx.fillText(num, 300, 108);
4089}
4090
4091function start() {
4092 for (var i = 0; i < testDivs.length; ++i) {
4093 tests[i] = null;
4094 }
4095 testIndex = 0;
4096 drawTop();
4097 window.addEventListener('keypress', doKeyPress, true);
4098 window.addEventListener('keydown', doKeyDown, true);
4099 window.onresize = function() {
4100 drawTop();
4101 }
4102 /*
4103 window.onpagehide = function() {
4104 disableClick = true;
4105 }
4106 */
4107 window.onpageshow = function () {
4108 disableClick = false;
4109 }
4110}
4111
4112</script>
4113</head>
4114
4115<body onLoad="start();">
4116<canvas id="canvas" width="750" height="500"
4117 onmousemove="handleMouseOver()"
4118 onclick="handleMouseClick()"
4119 ></canvas >
4120</body>
4121</html>