blob: 5aa1068a0c03f1de3ce6973aa6a2740b2b78b88d [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
caryclark08bc8482015-04-24 09:08:57 -07005<div id="cubics6d">
6seg=1 {{{3, 5}, {1.8377223f, 5}, {2.36405635f, 3.98683286f}, {3.00889349f, 2.74555302f}}}
7seg=2 {{{3.00889349f, 2.74555302f}, {3.47366595f, 1.85088933f}, {4, 0.837722301f}, {4, 0}}}
8seg=3 {{{4, 0}, {3, 5}}}
caryclark03b03ca2015-04-23 09:13:37 -07009op diff
caryclark08bc8482015-04-24 09:08:57 -070010seg=4 {{{2, 4}, {1.18350339f, 4}, {1.53367352f, 3.83333325f}, {2.2340138f, 3.5f}}}
11seg=5 {{{2.2340138f, 3.5f}, {3.2491498f, 3.01683664f}, {5, 2.18350339f}, {5, 1}}}
12seg=6 {{{5, 1}, {2, 4}}}
13debugShowCubicIntersection wtTs[0]=1 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{3.00889349,2.74555302}} wnTs[0]=0 {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}}
14debugShowCubicLineIntersection wtTs[0]=0 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{3,5}} wnTs[0]=1 {{{4,0}, {3,5}}}
15debugShowCubicLineIntersection wtTs[0]=0.602095725 {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} {{3.78703713,1.06481469}} wtTs[1]=1 {{4,0}} wnTs[0]=0.212963 {{{4,0}, {3,5}}} wnTs[1]=0
16SkOpSegment::addT insert t=0.602095725 segID=2 spanID=13
17SkOpSegment::addT insert t=0.212962933 segID=3 spanID=14
18debugShowCubicIntersection wtTs[0]=0.860380171 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{2.75000095,3.24999785}} wnTs[0]=0.155051 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}}
19SkOpSegment::addT insert t=0.860380171 segID=1 spanID=15
20SkOpSegment::addT insert t=0.155051471 segID=5 spanID=16
21debugShowCubicLineIntersection wtTs[0]=0.860379476 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{2.74999976,3.25000024}} wnTs[0]=0.75 {{{5,1}, {2,4}}}
22SkOpSegment::addT insert t=0.860379476 segID=1 spanID=17
23SkOpSegment::addT insert t=0.750000104 segID=6 spanID=18
24debugShowCubicIntersection no intersect {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}}
25debugShowCubicLineIntersection no intersect {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} {{{5,1}, {2,4}}}
26debugShowCubicLineIntersection wtTs[0]=0.338765871 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} {{3.42231941,2.88840342}} wnTs[0]=0.577681 {{{4,0}, {3,5}}}
27SkOpSegment::addT insert t=0.57768066 segID=3 spanID=19
28SkOpSegment::addT insert t=0.338765871 segID=5 spanID=20
29debugShowLineIntersection wtTs[0]=0.5 {{{4,0}, {3,5}}} {{3.5,2.5}} wnTs[0]=0.5 {{{5,1}, {2,4}}}
30SkOpSegment::addT insert t=0.5 segID=3 spanID=21
31SkOpSegment::addT insert t=0.5 segID=6 spanID=22
32debugShowCubicIntersection wtTs[0]=1 {{{2,4}, {1.18350339,4}, {1.53367352,3.83333325}, {2.2340138,3.5}}} {{2.2340138,3.5}} wnTs[0]=0 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}}
33debugShowCubicLineIntersection wtTs[0]=0 {{{2,4}, {1.18350339,4}, {1.53367352,3.83333325}, {2.2340138,3.5}}} {{2,4}} wnTs[0]=1 {{{5,1}, {2,4}}}
34debugShowCubicLineIntersection wtTs[0]=0.155050964 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} {{2.75,3.25}} wtTs[1]=1 {{5,1}} wnTs[0]=0.75 {{{5,1}, {2,4}}} wnTs[1]=0
35SkOpSegment::addT insert t=0.155050964 segID=5 spanID=23
36SkOpSegment::addT alias t=0.750000024 segID=6 spanID=18
37SkOpSegment::sortAngles [1] tStart=0.860379476 [17]
38SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 T 11
39SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1
40SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
41SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
42SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [6/22] 19/19 tStart=0.750000104 tEnd=1 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 F 4
43SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1
44SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6
45SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
46SkOpAngle::after [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [6/22] 19/19 tStart=0.750000104 tEnd=1 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 F 5
47SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
48SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6
49SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
50SkOpAngle::after [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 < [6/22] 19/19 tStart=0.750000104 tEnd=1 < [1/1] 21/25 tStart=0.860379476 tEnd=0 T 4
51SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
52SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6
53SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1
54SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [5/13] 17/17 tStart=0.155050964 tEnd=0 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 F 4
55SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1
56SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5
57SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
58SkOpAngle::after [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [5/13] 17/17 tStart=0.155050964 tEnd=0 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 F 5
59SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
60SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5
61SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
62SkOpAngle::after [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 < [5/13] 17/17 tStart=0.155050964 tEnd=0 < [6/22] 19/19 tStart=0.750000104 tEnd=1 T 4
63SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
64SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5
65SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6
66SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [5/14] 17/17 tStart=0.155050964 tEnd=0.155051471 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 F 4
67SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1
68SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000036,3.25000024}, {2.75000035,3.24999785}, {2.75000095,3.24999785}}} id=5
69SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
70SkOpAngle::after [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [5/14] 17/17 tStart=0.155050964 tEnd=0.155051471 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 F 5
71SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6
72SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5
73SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
74SkOpAngle::after [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 < [5/14] 17/17 tStart=0.155050964 tEnd=0.155051471 < [5/13] 17/17 tStart=0.155050964 tEnd=0 T 11
75SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1
76SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5
77SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5
78SkOpSegment::sortAngles [1] tStart=0.860380171 [15]
79SkOpAngle::after [1/3] 19/19 tStart=0.860380171 tEnd=0.860379476 < [5/15] 1/2 tStart=0.155051471 tEnd=0.155050964 < [1/4] 5/5 tStart=0.860380171 tEnd=1 T 4
80SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.75000055,3.24999866}, {2.75000017,3.24999943}, {2.74999976,3.25000024}}} id=1
81SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.75000035,3.24999785}, {2.75000036,3.25000024}, {2.74999976,3.25000024}}} id=5
82SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.8311395,3.08772078}, {2.91886144,2.9188603}, {3.00889349,2.74555302}}} id=1
83SkOpAngle::after [1/3] 19/19 tStart=0.860380171 tEnd=0.860379476 < [5/16] 1/1 tStart=0.155051471 tEnd=0.338765871 < [5/15] 1/2 tStart=0.155051471 tEnd=0.155050964 T 11
84SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.75000055,3.24999866}, {2.75000017,3.24999943}, {2.74999976,3.25000024}}} id=1
85SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.96742763,3.14128448}, {3.1966737,3.02075395}, {3.42231941,2.88840342}}} id=5
86SkOpAngle::afterPart {{{2.75000095,3.24999785}, {3.75000071,2.74999781}, {5,1.99999945}, {5,1}}} id=5
87SkOpSegment::sortAngles [2] tStart=0.602095725 [13]
88SkOpAngle::after [2/5] 21/21 tStart=0.602095725 tEnd=0 < [3/7] 5/5 tStart=0.212962933 tEnd=0 < [2/6] 5/5 tStart=0.602095725 tEnd=1 F 11
89SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.59088584,1.62524693}, {3.288731,2.20687983}, {3.00889349,2.74555302}}} id=2
90SkOpAngle::afterPart {{{3.78703713,1.06481469}, {4,0}}} id=3
91SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.91666675,0.694444369}, {4,0.333333285}, {4,0}}} id=2
92SkOpAngle::after [2/5] 21/21 tStart=0.602095725 tEnd=0 < [3/8] 21/21 tStart=0.212962933 tEnd=0.5 < [2/6] 5/5 tStart=0.602095725 tEnd=1 T 12
93SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.59088584,1.62524693}, {3.288731,2.20687983}, {3.00889349,2.74555302}}} id=2
94SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.5,2.5}}} id=3
95SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.91666675,0.694444369}, {4,0.333333285}, {4,0}}} id=2
96SkOpSegment::sortAngles [3] tStart=0.212962933 [14]
97SkOpSegment::sortAngles [3] tStart=0.5 [21]
98SkOpAngle::after [3/9] 5/5 tStart=0.5 tEnd=0.212962933 < [6/19] 3/3 tStart=0.5 tEnd=0 < [3/10] 21/21 tStart=0.5 tEnd=0.57768066 F 4
99SkOpAngle::afterPart {{{3.5,2.5}, {3.78703713,1.06481469}}} id=3
100SkOpAngle::afterPart {{{3.5,2.5}, {5,1}}} id=6
101SkOpAngle::afterPart {{{3.5,2.5}, {3.42231941,2.88840342}}} id=3
102SkOpAngle::after [3/9] 5/5 tStart=0.5 tEnd=0.212962933 < [6/20] 19/19 tStart=0.5 tEnd=0.750000104 < [3/10] 21/21 tStart=0.5 tEnd=0.57768066 T 4
103SkOpAngle::afterPart {{{3.5,2.5}, {3.78703713,1.06481469}}} id=3
104SkOpAngle::afterPart {{{3.5,2.5}, {2.74999976,3.25000024}}} id=6
105SkOpAngle::afterPart {{{3.5,2.5}, {3.42231941,2.88840342}}} id=3
106SkOpSegment::sortAngles [3] tStart=0.57768066 [19]
107SkOpAngle::after [3/11] 5/5 tStart=0.57768066 tEnd=0.5 < [5/17] 17/17 tStart=0.338765871 tEnd=0.155051471 < [3/12] 21/21 tStart=0.57768066 tEnd=1 T 4
108SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.5,2.5}}} id=3
109SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.1966737,3.02075395}, {2.96742763,3.14128448}, {2.75000095,3.24999785}}} id=5
110SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3,5}}} id=3
111SkOpAngle::after [3/11] 5/5 tStart=0.57768066 tEnd=0.5 < [5/18] 1/5 tStart=0.338765871 tEnd=1 < [5/17] 17/17 tStart=0.338765871 tEnd=0.155051471 F 12
112SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.5,2.5}}} id=3
113SkOpAngle::afterPart {{{3.42231941,2.88840342}, {4.23447483,2.41204069}, {5,1.78257283}, {5,1}}} id=5
114SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.1966737,3.02075395}, {2.96742763,3.14128448}, {2.75000095,3.24999785}}} id=5
115SkOpAngle::after [5/17] 17/17 tStart=0.338765871 tEnd=0.155051471 < [5/18] 1/5 tStart=0.338765871 tEnd=1 < [3/12] 21/21 tStart=0.57768066 tEnd=1 F 4
116SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.1966737,3.02075395}, {2.96742763,3.14128448}, {2.75000095,3.24999785}}} id=5
117SkOpAngle::afterPart {{{3.42231941,2.88840342}, {4.23447483,2.41204069}, {5,1.78257283}, {5,1}}} id=5
118SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3,5}}} id=3
119SkOpAngle::after [3/12] 21/21 tStart=0.57768066 tEnd=1 < [5/18] 1/5 tStart=0.338765871 tEnd=1 < [3/11] 5/5 tStart=0.57768066 tEnd=0.5 T 11
120SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3,5}}} id=3
121SkOpAngle::afterPart {{{3.42231941,2.88840342}, {4.23447483,2.41204069}, {5,1.78257283}, {5,1}}} id=5
122SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.5,2.5}}} id=3
123SkOpSegment::sortAngles [5] tStart=0.155050964 [23]
124SkOpSegment::sortAngles [5] tStart=0.155051471 [16]
125SkOpSegment::sortAngles [5] tStart=0.338765871 [20]
126SkOpSegment::sortAngles [6] tStart=0.5 [22]
127SkOpSegment::sortAngles [6] tStart=0.750000104 [18]
128SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 (3,5) tEnd=0.860379476 windSum=? windValue=1 oppValue=0
129SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860379476 (2.74999976,3.25000024) tEnd=0.860380171 windSum=? windValue=1 oppValue=0
130SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 (2.75000095,3.24999785) tEnd=1 windSum=? windValue=1 oppValue=0
131SkOpSegment::debugShowActiveSpans id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 (3.00889349,2.74555302) tEnd=0.602095725 windSum=? windValue=1 oppValue=0
132SkOpSegment::debugShowActiveSpans id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0.602095725 (3.78703713,1.06481469) tEnd=1 windSum=? windValue=1 oppValue=0
133SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0 (4,0) tEnd=0.212962933 windSum=? windValue=1 oppValue=0
134SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.212962933 (3.78703713,1.06481469) tEnd=0.5 windSum=? windValue=1 oppValue=0
135SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=? windValue=1 oppValue=0
136SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.57768066 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0
137SkOpSegment::debugShowActiveSpans id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 (2,4) tEnd=1 windSum=? windValue=1 oppValue=0
138SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 (2.2340138,3.5) tEnd=0.155050964 windSum=? windValue=1 oppValue=0
139SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 (2.74999976,3.25000024) tEnd=0.155051471 windSum=? windValue=1 oppValue=0
140SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0
141SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0
142SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=? windValue=1 oppValue=0
143SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.5 (3.5,2.5) tEnd=0.750000104 windSum=? windValue=1 oppValue=0
144SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.750000104 (2.74999976,3.25000024) tEnd=1 windSum=? windValue=1 oppValue=0
145-SkOpSegment::findTop- baseAngle
146SkOpAngle::dumpOne [3/23] next=2/24 sect=21/21 s=0 [5] e=0.212962933 [14] sgn=-1 windVal=1 windSum=?
147SkOpAngle::dumpOne [2/24] next=3/23 sect=22/21 s=1 [4] e=0.602095725 [13] sgn=1 windVal=1 windSum=?
148-SkOpSegment::findTop- firstAngle
149SkOpAngle::dumpOne [3/23] next=2/24 sect=21/21 s=0 [5] e=0.212962933 [14] sgn=-1 windVal=1 windSum=?
150SkOpAngle::dumpOne [2/24] next=3/23 sect=22/21 s=1 [4] e=0.602095725 [13] sgn=1 windVal=1 windSum=?
151SkOpSegment::findTop id=3 s=0.212962933 e=0 (+) cw=-1 swap=-1 inflections=-1 monotonic=1
152SkOpSegment::markWinding id=3 (4,0 3,5) t=0 [5] (4,0) tEnd=0.212962933 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
caryclark03b03ca2015-04-23 09:13:37 -0700153SkOpSegment::nextChase mismatched signs
caryclark08bc8482015-04-24 09:08:57 -0700154SkOpSegment::markWinding id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0.602095725 [13] (3.78703713,1.06481469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
155SkOpSegment::markWinding id=3 (4,0 3,5) t=0 [5] (4,0) tEnd=0.212962933 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
156SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
caryclark03b03ca2015-04-23 09:13:37 -0700157SkOpSegment::nextChase mismatched signs
158SkOpSegment::findNextOp simple
caryclark08bc8482015-04-24 09:08:57 -0700159SkOpSegment::markDone id=3 (4,0 3,5) t=0 [5] (4,0) tEnd=0.212962933 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
160bridgeOp current id=3 from=(3.78703713,1.06481469) to=(4,0)
161SkOpSegment::markWinding id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 [3] (3.00889349,2.74555302) tEnd=0.602095725 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
162SkOpSegment::markWinding id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 [15] (2.75000095,3.24999785) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
163SkOpSegment::markAngle last segment=1 span=15 windSum=-1
164SkOpSegment::markWinding id=3 (4,0 3,5) t=0.212962933 [14] (3.78703713,1.06481469) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
caryclark03b03ca2015-04-23 09:13:37 -0700165SkOpSegment::markAngle last segment=3 span=21 windSum=?
166SkOpSegment::findNextOp
caryclark08bc8482015-04-24 09:08:57 -0700167SkOpAngle::dumpOne [2/6] next=3/7 sect=5/5 s=0.602095725 [13] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
168SkOpAngle::dumpOne [3/7] next=2/5 sect=5/5 s=0.212962933 [14] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
169SkOpAngle::dumpOne [2/5] next=3/8 sect=21/21 s=0.602095725 [13] e=0 [3] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0
170SkOpAngle::dumpOne [3/8] next=2/6 sect=21/21 s=0.212962933 [14] e=0.5 [21] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
171SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
172SkOpSegment::activeOp id=2 t=0.602095725 tEnd=0 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
173SkOpSegment::findNextOp chase.append segment=1 span=15 windSum=-1
174SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0.5 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
caryclark03b03ca2015-04-23 09:13:37 -0700175SkOpSegment::findNextOp chase.append segment=3 span=21 windSum=-2147483647
caryclark08bc8482015-04-24 09:08:57 -0700176SkOpSegment::markDone id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0.602095725 [13] (3.78703713,1.06481469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
177SkOpSegment::findNextOp from:[2] to:[3] start=4807220 end=4807892
178bridgeOp current id=2 from=(4,0) to=(3.78703713,1.06481469)
179path.moveTo(3.78703713,1.06481469);
180path.lineTo(4,0);
181path.cubicTo(4,0.333333284, 3.91666675,0.694444358, 3.78703713,1.06481469);
caryclark03b03ca2015-04-23 09:13:37 -0700182path.close();
caryclark08bc8482015-04-24 09:08:57 -0700183SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 (3,5) tEnd=0.860379476 windSum=? windValue=1 oppValue=0
184SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860379476 (2.74999976,3.25000024) tEnd=0.860380171 windSum=? windValue=1 oppValue=0
185SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 (2.75000095,3.24999785) tEnd=1 windSum=-1 windValue=1 oppValue=0
186SkOpSegment::debugShowActiveSpans id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 (3.00889349,2.74555302) tEnd=0.602095725 windSum=-1 windValue=1 oppValue=0
187SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.212962933 (3.78703713,1.06481469) tEnd=0.5 windSum=-1 windValue=1 oppValue=0
188SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=? windValue=1 oppValue=0
189SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.57768066 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0
190SkOpSegment::debugShowActiveSpans id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 (2,4) tEnd=1 windSum=? windValue=1 oppValue=0
191SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 (2.2340138,3.5) tEnd=0.155050964 windSum=? windValue=1 oppValue=0
192SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 (2.74999976,3.25000024) tEnd=0.155051471 windSum=? windValue=1 oppValue=0
193SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0
194SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0
195SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=? windValue=1 oppValue=0
196SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.5 (3.5,2.5) tEnd=0.750000104 windSum=? windValue=1 oppValue=0
197SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.750000104 (2.74999976,3.25000024) tEnd=1 windSum=? windValue=1 oppValue=0
198SkOpSegment::activeOp id=3 t=0.5 tEnd=0.212962933 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
199SkOpSegment::findNextOp
200SkOpAngle::dumpOne [3/8] next=2/6 sect=21/21 s=0.212962933 [14] e=0.5 [21] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
201SkOpAngle::dumpOne [2/6] next=3/7 sect=5/5 s=0.602095725 [13] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
202SkOpAngle::dumpOne [3/7] next=2/5 sect=5/5 s=0.212962933 [14] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
203SkOpAngle::dumpOne [2/5] next=3/8 sect=21/21 s=0.602095725 [13] e=0 [3] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0
204SkOpSegment::activeOp id=2 t=0.602095725 tEnd=1 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
205SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
206SkOpSegment::activeOp id=2 t=0.602095725 tEnd=0 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
207SkOpSegment::markDone id=3 (4,0 3,5) t=0.212962933 [14] (3.78703713,1.06481469) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
208SkOpSegment::findNextOp from:[3] to:[2] start=4807124 end=4805876
209bridgeOp current id=3 from=(3.5,2.5) to=(3.78703713,1.06481469)
210SkOpSegment::findNextOp simple
211SkOpSegment::markDone id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 [3] (3.00889349,2.74555302) tEnd=0.602095725 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
212bridgeOp current id=2 from=(3.78703713,1.06481469) to=(3.00889349,2.74555302)
213path.moveTo(3.5,2.5);
214path.lineTo(3.78703713,1.06481469);
215path.cubicTo(3.59088588,1.62524688, 3.2887311,2.20687985, 3.00889349,2.74555302);
216SkOpSegment::findNextOp
217SkOpAngle::dumpOne [1/4] next=1/3 sect=5/5 s=0.860380171 [15] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
218SkOpAngle::dumpOne [1/3] next=5/16 sect=19/19 s=0.860380171 [15] e=0.860379476 [17] sgn=1 windVal=1 windSum=?
219SkOpAngle::dumpOne [5/16] next=5/15 sect=1/1 s=0.155051471 [16] e=0.338765871 [20] sgn=-1 windVal=1 windSum=? unorderable operand
220SkOpAngle::dumpOne [5/15] next=1/4 sect=1/2 s=0.155051471 [16] e=0.155050964 [23] sgn=1 windVal=1 windSum=? unorderable operand
221SkOpSegment::activeOp id=1 t=0.860380171 tEnd=0.860379476 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
222SkOpSegment::activeOp id=5 t=0.155051471 tEnd=0.338765871 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
223SkOpSegment::activeOp id=5 t=0.155051471 tEnd=0.155050964 op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
224SkOpSegment::markDone id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 [15] (2.75000095,3.24999785) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
225SkOpSegment::findNextOp from:[1] to:[1] start=4807316 end=4807508
226bridgeOp current id=1 from=(3.00889349,2.74555302) to=(2.75000095,3.24999785)
227path.cubicTo(2.91886139,2.9188602, 2.83113956,3.08772087, 2.75000095,3.24999785);
228SkOpSegment::findNextOp
229SkOpAngle::dumpOne [1/2] next=5/14 sect=3/3 s=0.860379476 [17] e=0.860380171 [15] sgn=-1 windVal=1 windSum=?
230SkOpAngle::dumpOne [5/14] next=5/13 sect=17/17 s=0.155050964 [23] e=0.155051471 [16] sgn=-1 windVal=1 windSum=? unorderable operand
231SkOpAngle::dumpOne [5/13] next=6/22 sect=17/17 s=0.155050964 [23] e=0 [9] sgn=1 windVal=1 windSum=? unorderable operand
232SkOpAngle::dumpOne [6/22] next=1/1 sect=19/19 s=0.750000104 [18] e=1 [12] sgn=-1 windVal=1 windSum=? operand
233SkOpAngle::dumpOne [1/1] next=6/21 sect=21/25 s=0.860379476 [17] e=0 [1] sgn=1 windVal=1 windSum=?
234SkOpAngle::dumpOne [6/21] next=1/2 sect=3/3 s=0.750000104 [18] e=0.5 [22] sgn=1 windVal=1 windSum=? operand
235SkOpSegment::markDone id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860379476 [17] (2.74999976,3.25000024) tEnd=0.860380171 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
236SkOpSegment::markWinding id=6 (5,1 2,4) t=0.5 [22] (3.5,2.5) tEnd=0.750000104 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
caryclark03b03ca2015-04-23 09:13:37 -0700237SkOpSegment::markAngle last segment=6 span=18 windSum=?
caryclark08bc8482015-04-24 09:08:57 -0700238SkOpSegment::markWinding id=3 (4,0 3,5) t=0.5 [21] (3.5,2.5) tEnd=0.57768066 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
caryclark03b03ca2015-04-23 09:13:37 -0700239SkOpSegment::markAngle last segment=3 span=19 windSum=?
caryclark08bc8482015-04-24 09:08:57 -0700240SkOpSegment::markWinding id=6 (5,1 2,4) t=0 [11] (5,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
241SkOpSegment::markWinding id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 [20] (3.42231941,2.88840342) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
caryclark03b03ca2015-04-23 09:13:37 -0700242SkOpSegment::markAngle last segment=5 span=20 windSum=1
caryclark08bc8482015-04-24 09:08:57 -0700243SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 (3,5) tEnd=0.860379476 windSum=? windValue=1 oppValue=0
244SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=-1 windValue=1 oppValue=0
245SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.57768066 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0
246SkOpSegment::debugShowActiveSpans id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 (2,4) tEnd=1 windSum=? windValue=1 oppValue=0
247SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 (2.2340138,3.5) tEnd=0.155050964 windSum=? windValue=1 oppValue=0
248SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 (2.74999976,3.25000024) tEnd=0.155051471 windSum=? windValue=1 oppValue=0
249SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0
250SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=1 windValue=1 oppValue=0
251SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=1 windValue=1 oppValue=0
252SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.5 (3.5,2.5) tEnd=0.750000104 windSum=1 windValue=1 oppValue=0
253SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.750000104 (2.74999976,3.25000024) tEnd=1 windSum=? windValue=1 oppValue=0
254SkOpSegment::activeOp id=6 t=0.5 tEnd=0.750000104 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
255SkOpSegment::markWinding id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 [1] (3,5) tEnd=0.860379476 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
256SkOpSegment::markWinding id=3 (4,0 3,5) t=0.57768066 [19] (3.42231941,2.88840342) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
257SkOpSegment::markAngle last segment=3 span=19 windSum=-1
caryclark03b03ca2015-04-23 09:13:37 -0700258SkOpSegment::findNextOp
caryclark08bc8482015-04-24 09:08:57 -0700259SkOpAngle::dumpOne [6/21] next=1/2 sect=3/3 s=0.750000104 [18] e=0.5 [22] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-1 operand
260SkOpAngle::dumpOne [1/2] next=5/14 sect=3/3 s=0.860379476 [17] e=0.860380171 [15] sgn=-1 windVal=1 windSum=? done
261SkOpAngle::dumpOne [5/14] next=5/13 sect=17/17 s=0.155050964 [23] e=0.155051471 [16] sgn=-1 windVal=1 windSum=? unorderable operand
262SkOpAngle::dumpOne [5/13] next=6/22 sect=17/17 s=0.155050964 [23] e=0 [9] sgn=1 windVal=1 windSum=? unorderable operand
263SkOpAngle::dumpOne [6/22] next=1/1 sect=19/19 s=0.750000104 [18] e=1 [12] sgn=-1 windVal=1 windSum=? operand
264SkOpAngle::dumpOne [1/1] next=6/21 sect=21/25 s=0.860379476 [17] e=0 [1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=1
265SkOpSegment::activeOp id=1 t=0.860379476 tEnd=0.860380171 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
266SkOpSegment::activeOp id=5 t=0.155050964 tEnd=0.155051471 op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
267SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 [23] (2.74999976,3.25000024) tEnd=0.155051471 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
268SkOpSegment::activeOp id=5 t=0.155050964 tEnd=0 op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
269SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 [9] (2.2340138,3.5) tEnd=0.155050964 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
270SkOpSegment::markDone id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 [7] (2,4) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
271SkOpSegment::markDone id=6 (5,1 2,4) t=0.750000104 [18] (2.74999976,3.25000024) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
272SkOpSegment::activeOp id=6 t=0.750000104 tEnd=1 op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
273SkOpSegment::activeOp id=1 t=0.860379476 tEnd=0 op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
274SkOpSegment::markDone id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 [1] (3,5) tEnd=0.860379476 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
275SkOpSegment::markDone id=3 (4,0 3,5) t=0.57768066 [19] (3.42231941,2.88840342) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
276SkOpSegment::findNextOp chase.append segment=3 span=19 windSum=-1
277SkOpSegment::markDone id=6 (5,1 2,4) t=0.5 [22] (3.5,2.5) tEnd=0.750000104 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
278SkOpSegment::findNextOp from:[6] to:[1] start=4807508 end=4807316
279bridgeOp current id=6 from=(3.5,2.5) to=(2.74999976,3.25000024)
280path.moveTo(3.5,2.5);
281path.lineTo(2.74999976,3.25000024);
282SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=-1 windValue=1 oppValue=0
283SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0
284SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=1 windValue=1 oppValue=0
285SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=1 windValue=1 oppValue=0
286SkOpSegment::activeOp id=5 t=0.338765871 tEnd=1 op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
287SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 [20] (3.42231941,2.88840342) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
288SkOpSegment::markDone id=6 (5,1 2,4) t=0 [11] (5,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
289bridgeOp chase.append id=6 windSum=1
290SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=-1 windValue=1 oppValue=0
291SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0
292SkOpSegment::activeOp id=3 t=0.5 tEnd=0.57768066 op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
293SkOpSegment::markDone id=3 (4,0 3,5) t=0.5 [21] (3.5,2.5) tEnd=0.57768066 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
294SkOpSegment::markWinding id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 [16] (2.75000095,3.24999785) tEnd=0.338765871 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
295SkOpSegment::markAngle last segment=5 span=16 windSum=1
296SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=1 windValue=1 oppValue=0
297SkOpSegment::activeOp id=5 t=0.338765871 tEnd=0.155051471 op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
298SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 [16] (2.75000095,3.24999785) tEnd=0.338765871 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
caryclarkdac1d172014-06-17 05:15:38 -0700299</div>
caryclark54359292015-03-26 07:52:43 -0700300
caryclarkdac1d172014-06-17 05:15:38 -0700301</div>
302
303<script type="text/javascript">
304
305var testDivs = [
caryclark08bc8482015-04-24 09:08:57 -0700306 cubics6d,
caryclarkdac1d172014-06-17 05:15:38 -0700307];
308
309var decimal_places = 3; // make this 3 to show more precision
310
311var tests = [];
312var testLines = [];
313var testTitles = [];
314var testIndex = 0;
315var ctx;
316
317var xmin, xmax, focusXmin, focusXmax;
318var ymin, ymax, focusYmin, focusYmax;
319var scale;
320var mouseX, mouseY;
321var srcLeft, srcTop;
322var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700323var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700324var curveT = 0;
325
326var pt_labels = 2;
327var collect_bounds = false;
328var control_lines = 0;
329var curve_t = false;
330var debug_xy = 1;
331var focus_enabled = false;
332var focus_on_selection = false;
333var step_limit = 0;
334var draw_active = false;
335var draw_add = false;
336var draw_angle = 0;
337var draw_deriviatives = 0;
338var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700339var draw_id = false;
340var draw_intersection = 0;
341var draw_intersectT = false;
342var draw_legend = true;
343var draw_log = false;
344var draw_mark = false;
345var draw_midpoint = false;
346var draw_op = 0;
347var draw_sequence = false;
348var draw_sort = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700349var draw_top = false;
caryclarkdac1d172014-06-17 05:15:38 -0700350var draw_path = 3;
351var draw_computed = 0;
352var retina_scale = !!window.devicePixelRatio;
353
354var activeCount = 0;
355var addCount = 0;
356var angleCount = 0;
357var opCount = 0;
358var sectCount = 0;
359var sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700360var topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700361var markCount = 0;
362var activeMax = 0;
363var addMax = 0;
364var angleMax = 0;
365var sectMax = 0;
366var sectMax2 = 0;
367var sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700368var topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700369var markMax = 0;
370var opMax = 0;
371var stepMax = 0;
372var lastIndex = 0;
373var hasPath = false;
374var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700375var angleBetween = false;
376var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700377
378var firstActiveSpan = -1;
379var logStart = -1;
380var logRange = 0;
381
382var SPAN_ID = 0;
383var SPAN_X1 = SPAN_ID + 1;
384var SPAN_Y1 = SPAN_X1 + 1;
385var SPAN_X2 = SPAN_Y1 + 1;
386var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700387
caryclarkdac1d172014-06-17 05:15:38 -0700388var SPAN_L_T = SPAN_Y2 + 1;
389var SPAN_L_TX = SPAN_L_T + 1;
390var SPAN_L_TY = SPAN_L_TX + 1;
391var SPAN_L_TEND = SPAN_L_TY + 1;
392var SPAN_L_OTHER = SPAN_L_TEND + 1;
393var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
394var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
395var SPAN_L_SUM = SPAN_L_OTHERI + 1;
396var SPAN_L_VAL = SPAN_L_SUM + 1;
397var SPAN_L_OPP = SPAN_L_VAL + 1;
398
399var SPAN_X3 = SPAN_Y2 + 1;
400var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700401
caryclarkdac1d172014-06-17 05:15:38 -0700402var SPAN_Q_T = SPAN_Y3 + 1;
403var SPAN_Q_TX = SPAN_Q_T + 1;
404var SPAN_Q_TY = SPAN_Q_TX + 1;
405var SPAN_Q_TEND = SPAN_Q_TY + 1;
406var SPAN_Q_OTHER = SPAN_Q_TEND + 1;
407var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
408var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
409var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
410var SPAN_Q_VAL = SPAN_Q_SUM + 1;
411var SPAN_Q_OPP = SPAN_Q_VAL + 1;
412
caryclark1049f122015-04-20 08:31:59 -0700413var SPAN_K_W = SPAN_Y3 + 1;
414var SPAN_K_T = SPAN_K_W + 1;
415var SPAN_K_TX = SPAN_K_T + 1;
416var SPAN_K_TY = SPAN_K_TX + 1;
417var SPAN_K_TEND = SPAN_K_TY + 1;
418var SPAN_K_OTHER = SPAN_K_TEND + 1;
419var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
420var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
421var SPAN_K_SUM = SPAN_K_OTHERI + 1;
422var SPAN_K_VAL = SPAN_K_SUM + 1;
423var SPAN_K_OPP = SPAN_K_VAL + 1;
424
caryclarkdac1d172014-06-17 05:15:38 -0700425var SPAN_X4 = SPAN_Y3 + 1;
426var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700427
caryclarkdac1d172014-06-17 05:15:38 -0700428var SPAN_C_T = SPAN_Y4 + 1;
429var SPAN_C_TX = SPAN_C_T + 1;
430var SPAN_C_TY = SPAN_C_TX + 1;
431var SPAN_C_TEND = SPAN_C_TY + 1;
432var SPAN_C_OTHER = SPAN_C_TEND + 1;
433var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
434var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
435var SPAN_C_SUM = SPAN_C_OTHERI + 1;
436var SPAN_C_VAL = SPAN_C_SUM + 1;
437var SPAN_C_OPP = SPAN_C_VAL + 1;
438
439var ACTIVE_LINE_SPAN = 1;
440var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700441var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
442var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700443
444var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
445var ADD_LINETO = ADD_MOVETO + 1;
446var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700447var ADD_CONICTO = ADD_QUADTO + 1;
448var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700449var ADD_CLOSE = ADD_CUBICTO + 1;
450var ADD_FILL = ADD_CLOSE + 1;
451
452var PATH_LINE = ADD_FILL + 1;
453var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700454var PATH_CONIC = PATH_QUAD + 1;
455var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700456
457var INTERSECT_LINE = PATH_CUBIC + 1;
458var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
459var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
460var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
461var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
462var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
463var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
464var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
465var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700466var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
467var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
468var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
469var INTERSECT_CONIC = INTERSECT_CONIC_LINE_NO + 1;
470var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
471var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
472var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700473var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
474var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
475var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
476var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
477var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
478var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
479var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
480var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
481var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
482var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
483var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
484var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
485var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
486var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
487// FIXME: add cubic 5- 9
488var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
489
490var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
491var SORT_BINARY = SORT_UNARY + 1;
492
493var OP_DIFFERENCE = SORT_BINARY + 1;
494var OP_INTERSECT = OP_DIFFERENCE + 1;
495var OP_UNION = OP_INTERSECT + 1;
496var OP_XOR = OP_UNION + 1;
497
498var MARK_LINE = OP_XOR + 1;
499var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700500var MARK_CONIC = MARK_QUAD + 1;
501var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700502var MARK_DONE_LINE = MARK_CUBIC + 1;
503var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700504var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
505var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700506var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
507var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700508var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
509var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700510var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
511var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700512var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
513var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700514var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
515var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700516var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
517var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700518var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
519var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700520var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
521var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700522var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
523
524var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
525var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
526
527var ANGLE_AFTER = COMPUTED_SET_2;
caryclark54359292015-03-26 07:52:43 -0700528var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700529
caryclark54359292015-03-26 07:52:43 -0700530var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700531
532var FRAG_TYPE_LAST = ACTIVE_OP;
533
534var REC_TYPE_UNKNOWN = -1;
535var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700536var REC_TYPE_PATH2 = 1;
537var REC_TYPE_SECT = 2;
538var REC_TYPE_ACTIVE = 3;
539var REC_TYPE_ADD = 4;
540var REC_TYPE_SORT = 5;
541var REC_TYPE_OP = 6;
542var REC_TYPE_MARK = 7;
543var REC_TYPE_COMPUTED = 8;
544var REC_TYPE_COIN = 9;
545var REC_TYPE_ANGLE = 10;
546var REC_TYPE_ACTIVE_OP = 11;
547var REC_TYPE_AFTERPART = 12;
caryclark03b03ca2015-04-23 09:13:37 -0700548var REC_TYPE_TOP = 13;
549var REC_TYPE_LAST = REC_TYPE_TOP;
caryclarkdac1d172014-06-17 05:15:38 -0700550
551function strs_to_nums(strs) {
552 var result = [];
553 for (var idx = 1; idx < strs.length; ++idx) {
554 var str = strs[idx];
555 var num = parseFloat(str);
556 if (isNaN(num)) {
557 result.push(str);
558 } else {
559 result.push(num);
560 }
561 }
562 return result;
563}
564
565function filter_str_by(id, str, regex, array) {
566 if (regex.test(str)) {
567 var strs = regex.exec(str);
568 var result = strs_to_nums(strs);
569 array.push(id);
570 array.push(result);
571 return true;
572 }
573 return false;
574}
575
576function construct_regexp2(pattern) {
577 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
578 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
579 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700580 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700581 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
582 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
583 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700584 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700585 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
586 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
587 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700588 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700589 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700590 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700591 escape = escape.replace(/NUM/g, "(-?\\d+)");
592 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
593 return new RegExp(escape, 'i');
594}
595
596function construct_regexp2c(pattern) {
597 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
598 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700599 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700600 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700601 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
602 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700603 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700604 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700605 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
caryclark54359292015-03-26 07:52:43 -0700606 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 -0700607 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700608 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700609 escape = escape.replace(/OPER/g, "[a-z]+");
610 escape = escape.replace(/PATH/g, "pathB?");
611 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700612 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700613 escape = escape.replace(/NUM/g, "(-?\\d+)");
614 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
615 return new RegExp(escape, 'i');
616}
617
618function match_regexp(str, lineNo, array, id, pattern) {
619 var regex = construct_regexp2(pattern);
620 if (filter_str_by(id, str, regex, array)) {
621 return true;
622 }
623 regex = construct_regexp2c(pattern);
624 return filter_str_by(id, str, regex, array);
625}
626
627function endsWith(str, suffix) {
628 return str.indexOf(suffix, str.length - suffix.length) !== -1;
629}
630
631function parse_all(test) {
632 var lines = test.match(/[^\r\n]+/g);
633 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
634 var record = [];
635 var recType = REC_TYPE_UNKNOWN;
636 var lastLineNo;
637 var moveX, moveY;
638 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
639 var line = lines[lineNo];
640 if (line.length == 0) {
641 continue;
642 }
643 var opStart = "SkOpSegment::";
644 if (line.lastIndexOf(opStart, 0) === 0) {
645 line = line.substr(opStart.length);
646 }
647 var angleStart = "SkOpAngle::";
648 if (line.lastIndexOf(angleStart, 0) === 0) {
649 line = line.substr(angleStart.length);
650 }
caryclark54359292015-03-26 07:52:43 -0700651 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
652 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclarkdac1d172014-06-17 05:15:38 -0700653 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
caryclark54359292015-03-26 07:52:43 -0700654 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700655 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
656 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
657 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
658 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
659 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
caryclark03b03ca2015-04-23 09:13:37 -0700660 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
caryclarkdac1d172014-06-17 05:15:38 -0700661 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
662 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
663 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
664 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
665 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700666 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700667 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
668 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
669 : REC_TYPE_UNKNOWN;
670 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
671 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
672 if (recType != REC_TYPE_UNKNOWN) {
673 records.push(recType);
674 records.push(lastLineNo);
675 records.push(record);
676 }
677 record = [];
678 recType = type;
679 lastLineNo = lineNo;
680 }
681 var found = false;
682 switch (recType) {
683 case REC_TYPE_ACTIVE:
684 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark54359292015-03-26 07:52:43 -0700685" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700686 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark54359292015-03-26 07:52:43 -0700687" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclark1049f122015-04-20 08:31:59 -0700688 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
689" id=IDX CONIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700690 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark54359292015-03-26 07:52:43 -0700691" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700692 );
693 break;
694 case REC_TYPE_ACTIVE_OP:
695 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
696" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
697 );
698 break;
699 case REC_TYPE_ADD:
700 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
701 moveX = record[1][0];
702 moveY = record[1][1];
703 found = true;
704 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
705 record[1].unshift(moveY);
706 record[1].unshift(moveX);
707 moveX = record[1][2];
708 moveY = record[1][3];
709 found = true;
710 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
711 record[1].unshift(moveY);
712 record[1].unshift(moveX);
713 moveX = record[1][4];
714 moveY = record[1][5];
715 found = true;
caryclark1049f122015-04-20 08:31:59 -0700716 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
717 record[1].unshift(moveY);
718 record[1].unshift(moveX);
719 moveX = record[1][4];
720 moveY = record[1][5];
721 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700722 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
723 record[1].unshift(moveY);
724 record[1].unshift(moveX);
725 moveX = record[1][6];
726 moveY = record[1][7];
727 found = true;
728 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
729 found = true;
730 } else {
731 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
732 }
733 break;
caryclark54359292015-03-26 07:52:43 -0700734 case REC_TYPE_AFTERPART:
735 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL")
736 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL")
caryclark1049f122015-04-20 08:31:59 -0700737 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL")
caryclark54359292015-03-26 07:52:43 -0700738 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL")
739 break;
caryclarkdac1d172014-06-17 05:15:38 -0700740 case REC_TYPE_ANGLE:
741 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
caryclarkdac1d172014-06-17 05:15:38 -0700742"[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");
743 break;
744 case REC_TYPE_COIN:
745 found = true;
746 break;
747 case REC_TYPE_COMPUTED:
748 found = line == "computed quadratics given"
749 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
750 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
751 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -0700752 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -0700753 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
754 );
755 break;
756 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700757 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
758 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700759 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -0700760 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
761 );
762 break;
763 case REC_TYPE_PATH2:
764 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
765 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -0700766 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -0700767 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -0700768 );
769 break;
770 case REC_TYPE_SECT:
771 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
772" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
773 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
774" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
775 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
776" no intersect LINE_VAL LINE_VAL"
777 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
778" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
779 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
780" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
781 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
782" no intersect QUAD_VAL LINE_VAL"
783 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
784" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
785 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
786" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
787 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
788" no intersect QUAD_VAL QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700789 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
790" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
791 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
792" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
793 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
794" no intersect CONIC_VAL LINE_VAL"
795 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
796" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
797 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
798" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
799 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
800" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -0700801 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
802" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
803 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
804" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
805 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
806" 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"
807 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
808" no intersect CUBIC_VAL LINE_VAL"
809 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
810" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
811 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
812" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
813 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
814" 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"
815 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
816" 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"
817 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
818" no intersect CUBIC_VAL QUAD_VAL"
819 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
820" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
821 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
822" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
823 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
824" 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"
825 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
826" 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"
827 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
828" no intersect CUBIC_VAL CUBIC_VAL"
829 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
830" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
831 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
832" no self intersect CUBIC_VAL"
833 );
834 break;
835 case REC_TYPE_SORT:
836 var hasDone = / done/.test(line);
837 var hasUnorderable = / unorderable/.test(line);
838 var hasSmall = / small/.test(line);
839 var hasTiny = / tiny/.test(line);
840 var hasOperand = / operand/.test(line);
841 var hasStop = / stop/.test(line);
842 line.replace(/[ a-z]+$/, "");
843 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
844" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
845 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
846" [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"
847 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
848" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
849 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
850" [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"
851 );
852 if (found) {
853 record[1].push(hasDone);
854 record[1].push(hasUnorderable);
855 record[1].push(hasSmall);
856 record[1].push(hasTiny);
857 record[1].push(hasOperand);
858 record[1].push(hasStop);
859 }
860 break;
caryclark03b03ca2015-04-23 09:13:37 -0700861 case REC_TYPE_TOP:
862 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
863" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
864 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
865" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
866 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
867" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
868 );
869 break;
caryclarkdac1d172014-06-17 05:15:38 -0700870 case REC_TYPE_MARK:
871 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700872" 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 -0700873 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700874" 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 -0700875 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
876" 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 -0700877 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700878" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
879 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
880" 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"
881 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
882" 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 -0700883 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
884" 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 -0700885 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
886" 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 -0700887 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
888" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
889 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
890" 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 -0700891 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
892" 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 -0700893 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
894" 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 -0700895 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -0700896" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -0700897 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
898" last segment=IDX span=IDX windSum=OPT");
caryclarkdac1d172014-06-17 05:15:38 -0700899 break;
900 case REC_TYPE_OP:
901 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
902 || line.lastIndexOf("operator<", 0) === 0) {
903 found = true;
904 break;
905 }
caryclark54359292015-03-26 07:52:43 -0700906 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -0700907 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -0700908 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -0700909 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
910 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
911 );
912 break;
913 case REC_TYPE_UNKNOWN:
914 found = true;
915 break;
916 }
917 if (!found) {
918 console.log(line + " [" + lineNo + "] of type " + type + " not found");
919 }
920 }
921 if (recType != REC_TYPE_UNKNOWN) {
922 records.push(recType);
923 records.push(lastLineNo);
924 records.push(record);
925 }
926 if (records.length >= 1) {
927 tests[testIndex] = records;
928 testLines[testIndex] = lines;
929 }
930}
931
932function init(test) {
933 var canvas = document.getElementById('canvas');
934 if (!canvas.getContext) return;
935 ctx = canvas.getContext('2d');
936 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
937 var unscaledWidth = window.innerWidth - 20;
938 var unscaledHeight = window.innerHeight - 20;
939 screenWidth = unscaledWidth;
940 screenHeight = unscaledHeight;
941 canvas.width = unscaledWidth * resScale;
942 canvas.height = unscaledHeight * resScale;
943 canvas.style.width = unscaledWidth + 'px';
944 canvas.style.height = unscaledHeight + 'px';
945 if (resScale != 1) {
946 ctx.scale(resScale, resScale);
947 }
948 xmin = Infinity;
949 xmax = -Infinity;
950 ymin = Infinity;
951 ymax = -Infinity;
952 hasPath = hasComputedPath = false;
953 firstActiveSpan = -1;
954 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
955 var recType = test[tIndex];
956 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
957 console.log("unknown rec type: " + recType);
958 throw "stop execution";
959 }
960 var records = test[tIndex + 2];
961 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
962 var fragType = records[recordIndex];
963 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
964 console.log("unknown in range frag type: " + fragType);
965 throw "stop execution";
966 }
967 var frags = records[recordIndex + 1];
968 var first = 0;
969 var last = -1;
970 var first2 = 0;
971 var last2 = 0;
972 switch (recType) {
973 case REC_TYPE_COMPUTED:
974 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
975 break;
976 }
977 hasComputedPath = true;
978 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700979 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -0700980 switch (fragType) {
981 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -0700982 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -0700983 break;
caryclark1049f122015-04-20 08:31:59 -0700984 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -0700985 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -0700986 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -0700987 break;
988 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -0700989 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -0700990 break;
991 default:
992 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
993 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
994 throw "stop execution";
995 }
996 if (recType == REC_TYPE_PATH) {
997 hasPath = true;
998 }
999 break;
caryclark54359292015-03-26 07:52:43 -07001000 case REC_TYPE_PATH2:
1001 first = 1;
1002 switch (fragType) {
1003 case PATH_LINE:
1004 last = 5;
1005 break;
caryclark1049f122015-04-20 08:31:59 -07001006 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001007 case PATH_QUAD:
1008 last = 7;
1009 break;
1010 case PATH_CUBIC:
1011 last = 9;
1012 break;
1013 default:
1014 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
1015 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1016 throw "stop execution";
1017 }
1018 if (recType == REC_TYPE_PATH2) {
1019 hasPath = true;
1020 }
1021 break;
caryclarkdac1d172014-06-17 05:15:38 -07001022 case REC_TYPE_ACTIVE:
1023 if (firstActiveSpan < 0) {
1024 firstActiveSpan = tIndex;
1025 }
1026 first = 1;
1027 switch (fragType) {
1028 case ACTIVE_LINE_SPAN:
1029 last = 5;
1030 break;
caryclark1049f122015-04-20 08:31:59 -07001031 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -07001032 case ACTIVE_QUAD_SPAN:
1033 last = 7;
1034 break;
1035 case ACTIVE_CUBIC_SPAN:
1036 last = 9;
1037 break;
1038 default:
1039 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1040 throw "stop execution";
1041 }
1042 break;
1043 case REC_TYPE_ADD:
1044 switch (fragType) {
1045 case ADD_MOVETO:
1046 break;
1047 case ADD_LINETO:
1048 last = 4;
1049 break;
caryclark1049f122015-04-20 08:31:59 -07001050 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -07001051 case ADD_QUADTO:
1052 last = 6;
1053 break;
1054 case ADD_CUBICTO:
1055 last = 8;
1056 break;
1057 case ADD_CLOSE:
1058 case ADD_FILL:
1059 break;
1060 default:
1061 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1062 throw "stop execution";
1063 }
1064 break;
caryclark54359292015-03-26 07:52:43 -07001065 case REC_TYPE_AFTERPART:
1066 switch (fragType) {
1067 case PATH_LINE:
1068 last = 4;
1069 break;
caryclark1049f122015-04-20 08:31:59 -07001070 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001071 case PATH_QUAD:
1072 last = 6;
1073 break;
1074 case PATH_CUBIC:
1075 last = 8;
1076 break;
1077 default:
1078 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1079 throw "stop execution";
1080 }
1081 break;
caryclarkdac1d172014-06-17 05:15:38 -07001082 case REC_TYPE_SECT:
1083 switch (fragType) {
1084 case INTERSECT_LINE:
1085 first = 1; last = 5; first2 = 8; last2 = 12;
1086 break;
1087 case INTERSECT_LINE_2:
1088 first = 1; last = 5; first2 = 11; last2 = 15;
1089 break;
1090 case INTERSECT_LINE_NO:
1091 first = 0; last = 4; first2 = 4; last2 = 8;
1092 break;
caryclark1049f122015-04-20 08:31:59 -07001093 case INTERSECT_CONIC_LINE:
1094 first = 1; last = 7; first2 = 11; last2 = 15;
1095 break;
caryclarkdac1d172014-06-17 05:15:38 -07001096 case INTERSECT_QUAD_LINE:
1097 first = 1; last = 7; first2 = 10; last2 = 14;
1098 break;
caryclark1049f122015-04-20 08:31:59 -07001099 case INTERSECT_CONIC_LINE_2:
1100 first = 1; last = 7; first2 = 14; last2 = 18;
1101 break;
caryclarkdac1d172014-06-17 05:15:38 -07001102 case INTERSECT_QUAD_LINE_2:
1103 first = 1; last = 7; first2 = 13; last2 = 17;
1104 break;
caryclark1049f122015-04-20 08:31:59 -07001105 case INTERSECT_CONIC_LINE_NO:
1106 first = 0; last = 6; first2 = 7; last2 = 11;
1107 break;
caryclarkdac1d172014-06-17 05:15:38 -07001108 case INTERSECT_QUAD_LINE_NO:
1109 first = 0; last = 6; first2 = 6; last2 = 10;
1110 break;
caryclark1049f122015-04-20 08:31:59 -07001111 case INTERSECT_CONIC:
1112 first = 1; last = 7; first2 = 11; last2 = 17;
1113 break;
caryclarkdac1d172014-06-17 05:15:38 -07001114 case INTERSECT_QUAD:
1115 first = 1; last = 7; first2 = 10; last2 = 16;
1116 break;
caryclark1049f122015-04-20 08:31:59 -07001117 case INTERSECT_CONIC_2:
1118 first = 1; last = 7; first2 = 14; last2 = 20;
1119 break;
caryclarkdac1d172014-06-17 05:15:38 -07001120 case INTERSECT_QUAD_2:
1121 first = 1; last = 7; first2 = 13; last2 = 19;
1122 break;
caryclark1049f122015-04-20 08:31:59 -07001123 case INTERSECT_CONIC_NO:
1124 first = 0; last = 6; first2 = 7; last2 = 13;
1125 break;
caryclarkdac1d172014-06-17 05:15:38 -07001126 case INTERSECT_QUAD_NO:
1127 first = 0; last = 6; first2 = 6; last2 = 12;
1128 break;
1129 case INTERSECT_SELF_CUBIC:
1130 first = 1; last = 9;
1131 break;
1132 case INTERSECT_SELF_CUBIC_NO:
1133 first = 0; last = 8;
1134 break;
1135 case INTERSECT_CUBIC_LINE:
1136 first = 1; last = 9; first2 = 12; last2 = 16;
1137 break;
1138 case INTERSECT_CUBIC_LINE_2:
1139 first = 1; last = 9; first2 = 15; last2 = 19;
1140 break;
1141 case INTERSECT_CUBIC_LINE_3:
1142 first = 1; last = 9; first2 = 18; last2 = 22;
1143 break;
1144 case INTERSECT_CUBIC_LINE_NO:
1145 first = 0; last = 8; first2 = 8; last2 = 12;
1146 break;
1147 case INTERSECT_CUBIC_QUAD:
1148 first = 1; last = 9; first2 = 12; last2 = 18;
1149 break;
1150 case INTERSECT_CUBIC_QUAD_2:
1151 first = 1; last = 9; first2 = 15; last2 = 21;
1152 break;
1153 case INTERSECT_CUBIC_QUAD_3:
1154 first = 1; last = 9; first2 = 18; last2 = 24;
1155 break;
1156 case INTERSECT_CUBIC_QUAD_4:
1157 first = 1; last = 9; first2 = 21; last2 = 27;
1158 break;
1159 case INTERSECT_CUBIC_QUAD_NO:
1160 first = 0; last = 8; first2 = 8; last2 = 14;
1161 break;
1162 case INTERSECT_CUBIC:
1163 first = 1; last = 9; first2 = 12; last2 = 20;
1164 break;
1165 case INTERSECT_CUBIC_2:
1166 first = 1; last = 9; first2 = 15; last2 = 23;
1167 break;
1168 case INTERSECT_CUBIC_3:
1169 first = 1; last = 9; first2 = 18; last2 = 26;
1170 break;
1171 case INTERSECT_CUBIC_4:
1172 first = 1; last = 9; first2 = 21; last2 = 29;
1173 break;
1174 case INTERSECT_CUBIC_NO:
1175 first = 0; last = 8; first2 = 8; last2 = 16;
1176 break;
1177 default:
1178 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1179 throw "stop execution";
1180 }
1181 break;
1182 default:
1183 continue;
1184 }
1185 for (var idx = first; idx < last; idx += 2) {
1186 xmin = Math.min(xmin, frags[idx]);
1187 xmax = Math.max(xmax, frags[idx]);
1188 ymin = Math.min(ymin, frags[idx + 1]);
1189 ymax = Math.max(ymax, frags[idx + 1]);
1190 }
1191 for (var idx = first2; idx < last2; idx += 2) {
1192 xmin = Math.min(xmin, frags[idx]);
1193 xmax = Math.max(xmax, frags[idx]);
1194 ymin = Math.min(ymin, frags[idx + 1]);
1195 ymax = Math.max(ymax, frags[idx + 1]);
1196 }
1197 }
1198 }
1199 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1200 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1201 var recType = test[tIndex];
1202 var records = test[tIndex + 2];
1203 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1204 var fragType = records[recordIndex];
1205 var frags = records[recordIndex + 1];
1206 switch (recType) {
1207 case REC_TYPE_ACTIVE_OP:
1208 if (!draw_op) {
1209 break;
1210 }
1211 {
1212 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1213 curve_extremes(curve, angleBounds);
1214 }
1215 break;
1216 case REC_TYPE_ANGLE:
1217 if (!draw_angle) {
1218 break;
1219 }
caryclark54359292015-03-26 07:52:43 -07001220 {
caryclarkdac1d172014-06-17 05:15:38 -07001221 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1222 curve_extremes(curve, angleBounds);
1223 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1224 curve_extremes(curve, angleBounds);
1225 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1226 }
1227 break;
1228 case REC_TYPE_SORT:
1229 if (!draw_sort) {
1230 break;
1231 }
1232 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1233 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1234 curve_extremes(curve, angleBounds);
1235 }
1236 break;
caryclark03b03ca2015-04-23 09:13:37 -07001237 case REC_TYPE_TOP:
1238 if (!draw_top) {
1239 break;
1240 }
1241 {
1242 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1243 curve_extremes(curve, angleBounds);
1244 }
1245 break;
caryclarkdac1d172014-06-17 05:15:38 -07001246 }
1247 }
1248 }
1249 xmin = Math.min(xmin, angleBounds[0]);
1250 ymin = Math.min(ymin, angleBounds[1]);
1251 xmax = Math.max(xmax, angleBounds[2]);
1252 ymax = Math.max(ymax, angleBounds[3]);
1253 setScale(xmin, xmax, ymin, ymax);
1254 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001255 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001256 }
1257 if (hasPath == true && hasComputedPath == false && draw_computed) {
1258 draw_computed = 0;
1259 }
1260}
1261
1262function curveByID(test, id) {
caryclark54359292015-03-26 07:52:43 -07001263 var tIndex = -3;
1264 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001265 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001266 if (recType == REC_TYPE_OP) {
1267 continue;
1268 }
1269 if (recType != REC_TYPE_PATH) {
caryclarkdac1d172014-06-17 05:15:38 -07001270 return [];
1271 }
1272 var records = test[tIndex + 2];
1273 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1274 var fragType = records[recordIndex];
1275 var frags = records[recordIndex + 1];
1276 if (frags[0] == id) {
1277 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001278 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001279 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001280 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001281 return [frags[1], frags[2], frags[3], frags[4],
1282 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001283 case PATH_CONIC:
1284 return [frags[1], frags[2], frags[3], frags[4],
1285 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001286 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001287 return [frags[1], frags[2], frags[3], frags[4],
1288 frags[5], frags[6], frags[7], frags[8]];
1289 }
1290 }
1291 }
caryclarkdac1d172014-06-17 05:15:38 -07001292 }
1293 return [];
1294}
1295
1296function curvePartialByID(test, id, t0, t1) {
caryclark54359292015-03-26 07:52:43 -07001297 var tIndex = -3;
1298 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001299 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001300 if (recType == REC_TYPE_OP) {
1301 continue;
1302 }
1303 if (recType != REC_TYPE_PATH) {
caryclarkdac1d172014-06-17 05:15:38 -07001304 return [];
1305 }
1306 var records = test[tIndex + 2];
1307 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1308 var fragType = records[recordIndex];
1309 var frags = records[recordIndex + 1];
1310 if (frags[0] == id) {
1311 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001312 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001313 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001314 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001315 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1316 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001317 case PATH_CONIC:
1318 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1319 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001320 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001321 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1322 frags[5], frags[6], frags[7], frags[8], t0, t1);
1323 }
1324 }
1325 }
caryclarkdac1d172014-06-17 05:15:38 -07001326 }
1327 return [];
1328}
1329
1330function idByCurve(test, frag, type) {
caryclark54359292015-03-26 07:52:43 -07001331 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001332 while (tIndex < test.length) {
1333 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001334 if (recType != REC_TYPE_PATH) {
1335 ++tIndex;
1336 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001337 }
1338 var records = test[tIndex + 2];
1339 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1340 var fragType = records[recordIndex];
1341 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001342 if (frag.length != frags.length - 1) {
1343 continue;
1344 }
caryclarkdac1d172014-06-17 05:15:38 -07001345 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001346 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001347 if (frag[0] != frags[1] || frag[1] != frags[2]
1348 || frag[2] != frags[3] || frag[3] != frags[4]) {
1349 continue;
1350 }
1351 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001352 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001353 if (frag[0] != frags[1] || frag[1] != frags[2]
1354 || frag[2] != frags[3] || frag[3] != frags[4]
1355 || frag[4] != frags[5] || frag[5] != frags[6]) {
1356 continue;
1357 }
1358 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001359 case PATH_CONIC:
1360 if (frag[0] != frags[1] || frag[1] != frags[2]
1361 || frag[2] != frags[3] || frag[3] != frags[4]
1362 || frag[4] != frags[5] || frag[5] != frags[6]
1363 || frag[6] != frags[7]) {
1364 continue;
1365 }
1366 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001367 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001368 if (frag[0] != frags[1] || frag[1] != frags[2]
1369 || frag[2] != frags[3] || frag[3] != frags[4]
1370 || frag[4] != frags[5] || frag[5] != frags[6]
1371 || frag[6] != frags[7] || frag[7] != frags[8]) {
1372 continue;
1373 }
1374 return frags[0];
1375 }
1376 }
1377 ++tIndex;
1378 }
1379 return -1;
1380}
1381
1382function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001383 var length = curve.length == 7 ? 6 : curve.length;
caryclarkdac1d172014-06-17 05:15:38 -07001384 for (var index = 0; index < curve.length; index += 2) {
1385 var x = curve[index];
1386 var y = curve[index + 1];
1387 bounds[0] = Math.min(bounds[0], x);
1388 bounds[1] = Math.min(bounds[1], y);
1389 bounds[2] = Math.max(bounds[2], x);
1390 bounds[3] = Math.max(bounds[3], y);
1391 }
1392}
1393
1394function setScale(x0, x1, y0, y1) {
1395 var srcWidth = x1 - x0;
1396 var srcHeight = y1 - y0;
1397 var usableWidth = screenWidth;
1398 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1399 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1400 usableWidth -= (xDigits + yDigits) * 10;
1401 usableWidth -= decimal_places * 10;
1402 if (draw_legend) {
1403 usableWidth -= 40;
1404 }
1405 var hscale = usableWidth / srcWidth;
1406 var vscale = screenHeight / srcHeight;
1407 scale = Math.min(hscale, vscale);
1408 var invScale = 1 / scale;
1409 var sxmin = x0 - invScale * 5;
1410 var symin = y0 - invScale * 10;
1411 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1412 var symax = y1 + invScale * 10;
1413 srcWidth = sxmax - sxmin;
1414 srcHeight = symax - symin;
1415 hscale = usableWidth / srcWidth;
1416 vscale = screenHeight / srcHeight;
1417 scale = Math.min(hscale, vscale);
1418 srcLeft = sxmin;
1419 srcTop = symin;
1420}
1421
1422function drawArc(curve, op, from, to) {
1423 var type = PATH_LINE + (curve.length / 2 - 2);
1424 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1425 var dy = pt.y - curve[1];
1426 var dx = pt.x - curve[0];
1427 var dist = Math.sqrt(dy * dy + dx * dx);
1428 var _dist = dist * scale;
1429 var angle = Math.atan2(dy, dx);
1430 var _px = (curve[0] - srcLeft) * scale;
1431 var _py = (curve[1] - srcTop) * scale;
1432 var divisor = 4;
1433 var endDist;
1434 do {
1435 var ends = [];
1436 for (var index = -1; index <= 1; index += 2) {
1437 var px = Math.cos(index * Math.PI / divisor);
1438 var py = Math.sin(index * Math.PI / divisor);
1439 ends.push(px);
1440 ends.push(py);
1441 }
1442 var endDx = (ends[2] - ends[0]) * scale * dist;
1443 var endDy = (ends[3] - ends[1]) * scale * dist;
1444 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1445 if (endDist < 100) {
1446 break;
1447 }
1448 divisor *= 2;
1449 } while (true);
1450 if (endDist < 30) {
1451 return;
1452 }
1453 if (op) {
1454 divisor *= 2;
1455 }
1456 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1457 ctx.beginPath();
1458 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1459 ctx.stroke();
1460 var saveAlign = ctx.textAlign;
1461 var saveStyle = ctx.fillStyle;
1462 var saveFont = ctx.font;
1463 ctx.textAlign = "center";
1464 ctx.fillStyle = "black";
1465 ctx.font = "normal 24px Arial";
1466 divisor *= 0.8;
1467 for (var index = -1; index <= 1; index += 2) {
1468 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1469 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1470 var _px = (px - srcLeft) * scale;
1471 var _py = (py - srcTop) * scale;
1472 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1473 }
1474 ctx.textAlign = saveAlign;
1475 ctx.fillStyle = saveStyle;
1476 ctx.font = saveFont;
1477}
1478
1479function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001480 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1481 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001482 var x = drawnPts[pts];
1483 var y = drawnPts[pts + 1];
1484 if (px == x && py == y) {
1485 return;
1486 }
1487 }
1488 drawnPts.push(px);
1489 drawnPts.push(py);
1490 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1491 var _px = (px - srcLeft) * scale;
1492 var _py = (py - srcTop) * scale;
1493 ctx.beginPath();
1494 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1495 ctx.closePath();
1496 if (end) {
1497 ctx.fill();
1498 } else {
1499 ctx.stroke();
1500 }
1501 if (debug_xy) {
1502 ctx.textAlign = "left";
1503 ctx.fillText(label, _px + 5, _py);
1504 }
1505}
1506
caryclark1049f122015-04-20 08:31:59 -07001507function coordCount(curveType) {
1508 switch (curveType) {
1509 case PATH_LINE:
1510 return 4;
1511 case PATH_QUAD:
1512 return 6;
1513 case PATH_CONIC:
1514 return 6;
1515 case PATH_CUBIC:
1516 return 8;
1517 }
1518 return -1;
1519}
1520
caryclarkdac1d172014-06-17 05:15:38 -07001521function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001522 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001523 for (var idx = 0; idx < count; idx += 2) {
1524 if (!drawControls && idx != 0 && idx != count - 2) {
1525 continue;
1526 }
1527 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1528 }
1529}
1530
1531function drawControlLines(curve, curveType, drawEnd) {
1532 if (curveType == PATH_LINE) {
1533 return;
1534 }
1535 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1536 drawLine(curve[0], curve[1], curve[2], curve[3]);
1537 drawLine(curve[2], curve[3], curve[4], curve[5]);
1538 if (curveType == PATH_CUBIC) {
1539 drawLine(curve[4], curve[5], curve[6], curve[7]);
1540 if (drawEnd > 1) {
1541 drawLine(curve[6], curve[7], curve[0], curve[1]);
1542 if (drawEnd > 2) {
1543 drawLine(curve[0], curve[1], curve[4], curve[5]);
1544 drawLine(curve[6], curve[7], curve[2], curve[3]);
1545 }
1546 }
1547 } else if (drawEnd > 1) {
1548 drawLine(curve[4], curve[5], curve[0], curve[1]);
1549 }
1550}
1551
1552function pointAtT(curve, curveType, t) {
1553 var xy = {};
1554 switch (curveType) {
1555 case PATH_LINE:
1556 var a = 1 - t;
1557 var b = t;
1558 xy.x = a * curve[0] + b * curve[2];
1559 xy.y = a * curve[1] + b * curve[3];
1560 break;
1561 case PATH_QUAD:
1562 var one_t = 1 - t;
1563 var a = one_t * one_t;
1564 var b = 2 * one_t * t;
1565 var c = t * t;
1566 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1567 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1568 break;
caryclark1049f122015-04-20 08:31:59 -07001569 case PATH_CONIC:
1570 var one_t = 1 - t;
1571 var a = one_t * one_t;
1572 var b = 2 * one_t * t;
1573 var c = t * t;
1574 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1575 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1576 var d = a + b * curve[6] + c;
1577 xy.x /= d;
1578 xy.y /= d;
1579 break;
caryclarkdac1d172014-06-17 05:15:38 -07001580 case PATH_CUBIC:
1581 var one_t = 1 - t;
1582 var one_t2 = one_t * one_t;
1583 var a = one_t2 * one_t;
1584 var b = 3 * one_t2 * t;
1585 var t2 = t * t;
1586 var c = 3 * one_t * t2;
1587 var d = t2 * t;
1588 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1589 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1590 break;
1591 }
1592 return xy;
1593}
1594
1595function drawPointAtT(curve, curveType) {
1596 var x, y;
1597 var xy = pointAtT(curve, curveType, curveT);
1598 drawPoint(xy.x, xy.y, true);
1599 if (!draw_intersectT) {
1600 return;
1601 }
1602 ctx.fillStyle = "red";
1603 drawTAtPointUp(xy.x, xy.y, curveT);
1604}
1605
1606function drawTAtPointUp(px, py, t) {
1607 var label = t.toFixed(decimal_places);
1608 var _px = (px - srcLeft)* scale;
1609 var _py = (py - srcTop) * scale;
1610 ctx.fillText(label, _px + 5, _py - 10);
1611}
1612
1613function drawTAtPointDown(px, py, t) {
1614 var label = t.toFixed(decimal_places);
1615 var _px = (px - srcLeft)* scale;
1616 var _py = (py - srcTop) * scale;
1617 ctx.fillText(label, _px + 5, _py + 10);
1618}
1619
1620function alreadyDrawnLine(x1, y1, x2, y2) {
1621 if (collect_bounds) {
1622 if (focus_enabled) {
1623 focusXmin = Math.min(focusXmin, x1, x2);
1624 focusYmin = Math.min(focusYmin, y1, y2);
1625 focusXmax = Math.max(focusXmax, x1, x2);
1626 focusYmax = Math.max(focusYmax, y1, y2);
1627 }
1628 return true;
1629 }
1630 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1631 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1632 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1633 return true;
1634 }
1635 }
1636 drawnLines.push(x1);
1637 drawnLines.push(y1);
1638 drawnLines.push(x2);
1639 drawnLines.push(y2);
1640 return false;
1641}
1642
1643function drawLine(x1, y1, x2, y2) {
1644 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1645 return;
1646 }
1647 ctx.beginPath();
1648 ctx.moveTo((x1 - srcLeft) * scale,
1649 (y1 - srcTop) * scale);
1650 ctx.lineTo((x2 - srcLeft) * scale,
1651 (y2 - srcTop) * scale);
1652 ctx.stroke();
1653}
1654
1655function linePartial(x1, y1, x2, y2, t1, t2) {
1656 var dx = x1 - x2;
1657 var dy = y1 - y2;
1658 var array = [
1659 x1 - t1 * dx,
1660 y1 - t1 * dy,
1661 x1 - t2 * dx,
1662 y1 - t2 * dy
1663 ];
1664 return array;
1665}
1666
1667function drawLinePartial(x1, y1, x2, y2, t1, t2) {
1668 var a = linePartial(x1, y1, x2, y2, t1, t2);
1669 var ax = a[0];
1670 var ay = a[1];
1671 var bx = a[2];
1672 var by = a[3];
1673 if (alreadyDrawnLine(ax, ay, bx, by)) {
1674 return;
1675 }
1676 ctx.beginPath();
1677 ctx.moveTo((ax - srcLeft) * scale,
1678 (ay - srcTop) * scale);
1679 ctx.lineTo((bx - srcLeft) * scale,
1680 (by - srcTop) * scale);
1681 ctx.stroke();
1682}
1683
1684function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
1685 if (collect_bounds) {
1686 if (focus_enabled) {
1687 focusXmin = Math.min(focusXmin, x1, x2, x3);
1688 focusYmin = Math.min(focusYmin, y1, y2, y3);
1689 focusXmax = Math.max(focusXmax, x1, x2, x3);
1690 focusYmax = Math.max(focusYmax, y1, y2, y3);
1691 }
1692 return true;
1693 }
1694 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
1695 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
1696 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
1697 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
1698 return true;
1699 }
1700 }
1701 drawnQuads.push(x1);
1702 drawnQuads.push(y1);
1703 drawnQuads.push(x2);
1704 drawnQuads.push(y2);
1705 drawnQuads.push(x3);
1706 drawnQuads.push(y3);
1707 return false;
1708}
1709
1710function drawQuad(x1, y1, x2, y2, x3, y3) {
1711 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
1712 return;
1713 }
1714 ctx.beginPath();
1715 ctx.moveTo((x1 - srcLeft) * scale,
1716 (y1 - srcTop) * scale);
1717 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
1718 (y2 - srcTop) * scale,
1719 (x3 - srcLeft) * scale,
1720 (y3 - srcTop) * scale);
1721 ctx.stroke();
1722}
1723
1724function interp(A, B, t) {
1725 return A + (B - A) * t;
1726}
1727
1728function interp_quad_coords(x1, x2, x3, t)
1729{
1730 var ab = interp(x1, x2, t);
1731 var bc = interp(x2, x3, t);
1732 var abc = interp(ab, bc, t);
1733 return abc;
1734}
1735
1736function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1737 var ax = interp_quad_coords(x1, x2, x3, t1);
1738 var ay = interp_quad_coords(y1, y2, y3, t1);
1739 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
1740 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
1741 var cx = interp_quad_coords(x1, x2, x3, t2);
1742 var cy = interp_quad_coords(y1, y2, y3, t2);
1743 var bx = 2*dx - (ax + cx)/2;
1744 var by = 2*dy - (ay + cy)/2;
1745 var array = [
1746 ax, ay, bx, by, cx, cy
1747 ];
1748 return array;
1749}
1750
1751function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1752 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
1753 var ax = a[0];
1754 var ay = a[1];
1755 var bx = a[2];
1756 var by = a[3];
1757 var cx = a[4];
1758 var cy = a[5];
1759 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
1760 return;
1761 }
1762 ctx.beginPath();
1763 ctx.moveTo((ax - srcLeft) * scale,
1764 (ay - srcTop) * scale);
1765 ctx.quadraticCurveTo((bx - srcLeft) * scale,
1766 (by - srcTop) * scale,
1767 (cx - srcLeft) * scale,
1768 (cy - srcTop) * scale);
1769 ctx.stroke();
1770}
1771
caryclark1049f122015-04-20 08:31:59 -07001772function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
1773 if (collect_bounds) {
1774 if (focus_enabled) {
1775 focusXmin = Math.min(focusXmin, x1, x2, x3);
1776 focusYmin = Math.min(focusYmin, y1, y2, y3);
1777 focusXmax = Math.max(focusXmax, x1, x2, x3);
1778 focusYmax = Math.max(focusYmax, y1, y2, y3);
1779 }
1780 return true;
1781 }
1782 for (var pts = 0; pts < drawnConics.length; pts += 8) {
1783 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
1784 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1785 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1786 && w == drawnCubics[pts + 6]) {
1787 return true;
1788 }
1789 }
1790 drawnConics.push(x1);
1791 drawnConics.push(y1);
1792 drawnConics.push(x2);
1793 drawnConics.push(y2);
1794 drawnConics.push(x3);
1795 drawnConics.push(y3);
1796 drawnCubics.push(w);
1797 return false;
1798}
1799
1800var kMaxConicToQuadPOW2 = 5;
1801
1802function computeQuadPOW2(curve, tol) {
1803 var a = curve[6] - 1;
1804 var k = a / (4 * (2 + a));
1805 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
1806 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
1807
1808 var error = Math.sqrt(x * x + y * y);
1809 var pow2;
1810 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
1811 if (error <= tol) {
1812 break;
1813 }
1814 error *= 0.25;
1815 }
1816 return pow2;
1817}
1818
1819function subdivide_w_value(w) {
1820 return Math.sqrt(0.5 + w * 0.5);
1821}
1822
1823function chop(curve, part1, part2) {
1824 var w = curve[6];
1825 var scale = 1 / (1 + w);
1826 part1[0] = curve[0];
1827 part1[1] = curve[1];
1828 part1[2] = (curve[0] + curve[2] * w) * scale;
1829 part1[3] = (curve[1] + curve[3] * w) * scale;
1830 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
1831 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
1832 part2[2] = (curve[2] * w + curve[4]) * scale;
1833 part2[3] = (curve[3] * w + curve[5]) * scale;
1834 part2[4] = curve[4];
1835 part2[5] = curve[5];
1836 part1[6] = part2[6] = subdivide_w_value(w);
1837}
1838
1839function subdivide(curve, level, pts) {
1840 if (0 == level) {
1841 pts.push(curve[2]);
1842 pts.push(curve[3]);
1843 pts.push(curve[4]);
1844 pts.push(curve[5]);
1845 } else {
1846 var part1 = [], part2 = [];
1847 chop(curve, part1, part2);
1848 --level;
1849 subdivide(part1, level, pts);
1850 subdivide(part2, level, pts);
1851 }
1852}
1853
1854function chopIntoQuadsPOW2(curve, pow2, pts) {
1855 subdivide(curve, pow2, pts);
1856 return 1 << pow2;
1857}
1858
1859function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
1860 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
1861 return;
1862 }
1863 ctx.beginPath();
1864 ctx.moveTo((x1 - srcLeft) * scale,
1865 (y1 - srcTop) * scale);
1866 var tol = 1 / scale;
1867 var curve = [x1, y1, x2, y2, x3, y3, w];
1868 var pow2 = computeQuadPOW2(curve, tol);
1869 var pts = [];
1870 chopIntoQuadsPOW2(curve, pow2, pts);
1871 for (var i = 0; i < pts.length; i += 4) {
1872 ctx.quadraticCurveTo(
1873 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
1874 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
1875 }
1876 ctx.stroke();
1877}
1878
1879function conic_eval_numerator(x1, x2, x3, w, t) {
1880 var src2w = x2 * w;
1881 var C = x1;
1882 var A = x3 - 2 * src2w + C;
1883 var B = 2 * (src2w - C);
1884 return (A * t + B) * t + C;
1885}
1886
1887
1888function conic_eval_denominator(w, t) {
1889 var B = 2 * (w - 1);
1890 var C = 1;
1891 var A = -B;
1892 return (A * t + B) * t + C;
1893}
1894
1895function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
1896 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
1897 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
1898 var az = conic_eval_denominator(w, t1);
1899 var midT = (t1 + t2) / 2;
1900 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
1901 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
1902 var dz = conic_eval_denominator(w, midT);
1903 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
1904 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
1905 var cz = conic_eval_denominator(w, t2);
1906 var bx = 2 * dx - (ax + cx) / 2;
1907 var by = 2 * dy - (ay + cy) / 2;
1908 var bz = 2 * dz - (az + cz) / 2;
1909 var dt = t2 - t1;
1910 var dt_1 = 1 - dt;
1911 var partW = (1 + dt * (w - 1)) / Math.sqrt(dt * dt + 2 * dt * dt_1 * w + dt_1 * dt_1);
1912 var array = [
1913 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, partW
1914 ];
1915 return array;
1916}
1917
1918function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
1919 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
1920 var ax = a[0];
1921 var ay = a[1];
1922 var bx = a[2];
1923 var by = a[3];
1924 var cx = a[4];
1925 var cy = a[5];
1926 var w_ = a[6];
1927 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
1928}
1929
caryclarkdac1d172014-06-17 05:15:38 -07001930function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
1931 if (collect_bounds) {
1932 if (focus_enabled) {
1933 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
1934 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
1935 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
1936 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
1937 }
1938 return true;
1939 }
1940 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
1941 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
1942 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1943 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1944 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
1945 return true;
1946 }
1947 }
1948 drawnCubics.push(x1);
1949 drawnCubics.push(y1);
1950 drawnCubics.push(x2);
1951 drawnCubics.push(y2);
1952 drawnCubics.push(x3);
1953 drawnCubics.push(y3);
1954 drawnCubics.push(x4);
1955 drawnCubics.push(y4);
1956 return false;
1957}
1958
1959function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
1960 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
1961 return;
1962 }
1963 ctx.beginPath();
1964 ctx.moveTo((x1 - srcLeft) * scale,
1965 (y1 - srcTop) * scale);
1966 ctx.bezierCurveTo((x2 - srcLeft) * scale,
1967 (y2 - srcTop) * scale,
1968 (x3 - srcLeft) * scale,
1969 (y3 - srcTop) * scale,
1970 (x4 - srcLeft) * scale,
1971 (y4 - srcTop) * scale);
1972 ctx.stroke();
1973}
1974
1975function interp_cubic_coords(x1, x2, x3, x4, t)
1976{
1977 var ab = interp(x1, x2, t);
1978 var bc = interp(x2, x3, t);
1979 var cd = interp(x3, x4, t);
1980 var abc = interp(ab, bc, t);
1981 var bcd = interp(bc, cd, t);
1982 var abcd = interp(abc, bcd, t);
1983 return abcd;
1984}
1985
1986function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
1987 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
1988 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
1989 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
1990 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
1991 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
1992 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
1993 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
1994 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
1995 var mx = ex * 27 - ax * 8 - dx;
1996 var my = ey * 27 - ay * 8 - dy;
1997 var nx = fx * 27 - ax - dx * 8;
1998 var ny = fy * 27 - ay - dy * 8;
1999 var bx = (mx * 2 - nx) / 18;
2000 var by = (my * 2 - ny) / 18;
2001 var cx = (nx * 2 - mx) / 18;
2002 var cy = (ny * 2 - my) / 18;
2003 var array = [
2004 ax, ay, bx, by, cx, cy, dx, dy
2005 ];
2006 return array;
2007}
2008
2009function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2010 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2011 var ax = a[0];
2012 var ay = a[1];
2013 var bx = a[2];
2014 var by = a[3];
2015 var cx = a[4];
2016 var cy = a[5];
2017 var dx = a[6];
2018 var dy = a[7];
2019 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
2020 return;
2021 }
2022 ctx.beginPath();
2023 ctx.moveTo((ax - srcLeft) * scale,
2024 (ay - srcTop) * scale);
2025 ctx.bezierCurveTo((bx - srcLeft) * scale,
2026 (by - srcTop) * scale,
2027 (cx - srcLeft) * scale,
2028 (cy - srcTop) * scale,
2029 (dx - srcLeft) * scale,
2030 (dy - srcTop) * scale);
2031 ctx.stroke();
2032}
2033
2034function drawCurve(c) {
2035 switch (c.length) {
2036 case 4:
2037 drawLine(c[0], c[1], c[2], c[3]);
2038 break;
2039 case 6:
2040 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
2041 break;
caryclark1049f122015-04-20 08:31:59 -07002042 case 7:
2043 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
2044 break;
caryclarkdac1d172014-06-17 05:15:38 -07002045 case 8:
2046 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
2047 break;
2048 }
2049}
2050
2051function boundsWidth(pts) {
2052 var min = pts[0];
2053 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07002054 var length = pts.length == 7 ? 6 : pts.length;
2055 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002056 min = Math.min(min, pts[idx]);
2057 max = Math.max(max, pts[idx]);
2058 }
2059 return max - min;
2060}
2061
2062function boundsHeight(pts) {
2063 var min = pts[1];
2064 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07002065 var length = pts.length == 7 ? 6 : pts.length;
2066 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002067 min = Math.min(min, pts[idx]);
2068 max = Math.max(max, pts[idx]);
2069 }
2070 return max - min;
2071}
2072
2073function tangent(pts) {
2074 var dx = pts[2] - pts[0];
2075 var dy = pts[3] - pts[1];
2076 if (dx == 0 && dy == 0 && pts.length > 4) {
2077 dx = pts[4] - pts[0];
2078 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002079 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002080 dx = pts[6] - pts[0];
2081 dy = pts[7] - pts[1];
2082 }
2083 }
2084 return Math.atan2(-dy, dx);
2085}
2086
2087function hodograph(cubic) {
2088 var hodo = [];
2089 hodo[0] = 3 * (cubic[2] - cubic[0]);
2090 hodo[1] = 3 * (cubic[3] - cubic[1]);
2091 hodo[2] = 3 * (cubic[4] - cubic[2]);
2092 hodo[3] = 3 * (cubic[5] - cubic[3]);
2093 hodo[4] = 3 * (cubic[6] - cubic[4]);
2094 hodo[5] = 3 * (cubic[7] - cubic[5]);
2095 return hodo;
2096}
2097
2098function hodograph2(cubic) {
2099 var quad = hodograph(cubic);
2100 var hodo = [];
2101 hodo[0] = 2 * (quad[2] - quad[0]);
2102 hodo[1] = 2 * (quad[3] - quad[1]);
2103 hodo[2] = 2 * (quad[4] - quad[2]);
2104 hodo[3] = 2 * (quad[5] - quad[3]);
2105 return hodo;
2106}
2107
2108function quadraticRootsReal(A, B, C, s) {
2109 if (A == 0) {
2110 if (B == 0) {
2111 s[0] = 0;
2112 return C == 0;
2113 }
2114 s[0] = -C / B;
2115 return 1;
2116 }
2117 /* normal form: x^2 + px + q = 0 */
2118 var p = B / (2 * A);
2119 var q = C / A;
2120 var p2 = p * p;
2121 if (p2 < q) {
2122 return 0;
2123 }
2124 var sqrt_D = 0;
2125 if (p2 > q) {
2126 sqrt_D = sqrt(p2 - q);
2127 }
2128 s[0] = sqrt_D - p;
2129 s[1] = -sqrt_D - p;
2130 return 1 + s[0] != s[1];
2131}
2132
2133function add_valid_ts(s, realRoots, t) {
2134 var foundRoots = 0;
2135 for (var index = 0; index < realRoots; ++index) {
2136 var tValue = s[index];
2137 if (tValue >= 0 && tValue <= 1) {
2138 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2139 if (t[idx2] != tValue) {
2140 t[foundRoots++] = tValue;
2141 }
2142 }
2143 }
2144 }
2145 return foundRoots;
2146}
2147
2148function quadraticRootsValidT(a, b, c, t) {
2149 var s = [];
2150 var realRoots = quadraticRootsReal(A, B, C, s);
2151 var foundRoots = add_valid_ts(s, realRoots, t);
2152 return foundRoots != 0;
2153}
2154
2155function find_cubic_inflections(cubic, tValues) {
2156 var Ax = src[2] - src[0];
2157 var Ay = src[3] - src[1];
2158 var Bx = src[4] - 2 * src[2] + src[0];
2159 var By = src[5] - 2 * src[3] + src[1];
2160 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2161 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2162 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2163 Ax * By - Ay * Bx, tValues);
2164}
2165
2166function dxy_at_t(curve, type, t) {
2167 var dxy = {};
2168 if (type == PATH_QUAD) {
2169 var a = t - 1;
2170 var b = 1 - 2 * t;
2171 var c = t;
2172 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2173 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002174 } else if (type == PATH_CONIC) {
2175 var p20x = curve[4] - curve[0];
2176 var p20y = curve[5] - curve[1];
2177 var p10xw = (curve[2] - curve[0]) * curve[6];
2178 var p10yw = (curve[3] - curve[1]) * curve[6];
2179 var coeff0x = curve[6] * p20x - p20x;
2180 var coeff0y = curve[6] * p20y - p20y;
2181 var coeff1x = p20x - 2 * p10xw;
2182 var coeff1y = p20y - 2 * p10yw;
2183 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2184 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002185 } else if (type == PATH_CUBIC) {
2186 var one_t = 1 - t;
2187 var a = curve[0];
2188 var b = curve[2];
2189 var c = curve[4];
2190 var d = curve[6];
2191 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2192 a = curve[1];
2193 b = curve[3];
2194 c = curve[5];
2195 d = curve[7];
2196 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2197 }
2198 return dxy;
2199}
2200
2201function drawLabel(num, px, py) {
2202 ctx.beginPath();
2203 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2204 ctx.closePath();
2205 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2206 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2207 ctx.stroke();
2208 ctx.fillStyle = "black";
2209 ctx.font = "normal 10px Arial";
2210 // ctx.rotate(0.001);
2211 ctx.fillText(num, px - 2, py + 3);
2212 // ctx.rotate(-0.001);
2213}
2214
2215function drawLabelX(ymin, num, loc) {
2216 var px = (loc - srcLeft) * scale;
2217 var py = (ymin - srcTop) * scale - 20;
2218 drawLabel(num, px, py);
2219}
2220
2221function drawLabelY(xmin, num, loc) {
2222 var px = (xmin - srcLeft) * scale - 20;
2223 var py = (loc - srcTop) * scale;
2224 drawLabel(num, px, py);
2225}
2226
2227function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2228 ctx.beginPath();
2229 ctx.moveTo(hx, hy - 100);
2230 ctx.lineTo(hx, hy);
2231 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2232 ctx.stroke();
2233 ctx.beginPath();
2234 ctx.moveTo(hx, hy);
2235 ctx.lineTo(hx, hy + 100);
2236 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2237 ctx.stroke();
2238 ctx.beginPath();
2239 ctx.moveTo(hx - 100, hy);
2240 ctx.lineTo(hx, hy);
2241 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2242 ctx.stroke();
2243 ctx.beginPath();
2244 ctx.moveTo(hx, hy);
2245 ctx.lineTo(hx + 100, hy);
2246 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2247 ctx.stroke();
2248}
2249
2250function scalexy(x, y, mag) {
2251 var length = Math.sqrt(x * x + y * y);
2252 return mag / length;
2253}
2254
caryclark03b03ca2015-04-23 09:13:37 -07002255function drawArrow(x, y, dx, dy, s) {
2256 var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
caryclarkdac1d172014-06-17 05:15:38 -07002257 dx *= dscale;
2258 dy *= dscale;
2259 ctx.beginPath();
2260 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2261 x += dx;
2262 y += dy;
2263 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2264 dx /= 10;
2265 dy /= 10;
2266 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2267 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2268 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2269 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2270 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2271 ctx.stroke();
2272}
2273
2274function x_at_t(curve, t) {
2275 var one_t = 1 - t;
2276 if (curve.length == 4) {
2277 return one_t * curve[0] + t * curve[2];
2278 }
2279 var one_t2 = one_t * one_t;
2280 var t2 = t * t;
2281 if (curve.length == 6) {
2282 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2283 }
caryclark1049f122015-04-20 08:31:59 -07002284 if (curve.length == 7) {
2285 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2286 / (one_t2 +2 * one_t * t * curve[6] + t2);
2287 }
caryclarkdac1d172014-06-17 05:15:38 -07002288 var a = one_t2 * one_t;
2289 var b = 3 * one_t2 * t;
2290 var c = 3 * one_t * t2;
2291 var d = t2 * t;
2292 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2293}
2294
2295function y_at_t(curve, t) {
2296 var one_t = 1 - t;
2297 if (curve.length == 4) {
2298 return one_t * curve[1] + t * curve[3];
2299 }
2300 var one_t2 = one_t * one_t;
2301 var t2 = t * t;
2302 if (curve.length == 6) {
2303 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2304 }
caryclark1049f122015-04-20 08:31:59 -07002305 if (curve.length == 7) {
2306 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2307 / (one_t2 +2 * one_t * t * curve[6] + t2);
2308 }
caryclarkdac1d172014-06-17 05:15:38 -07002309 var a = one_t2 * one_t;
2310 var b = 3 * one_t2 * t;
2311 var c = 3 * one_t * t2;
2312 var d = t2 * t;
2313 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2314}
2315
2316function drawOrder(curve, label) {
2317 var px = x_at_t(curve, 0.75);
2318 var py = y_at_t(curve, 0.75);
2319 var _px = (px - srcLeft) * scale;
2320 var _py = (py - srcTop) * scale;
2321 ctx.beginPath();
2322 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2323 ctx.closePath();
2324 ctx.fillStyle = "white";
2325 ctx.fill();
2326 if (label == 'L') {
2327 ctx.strokeStyle = "rgba(255,0,0, 1)";
2328 ctx.fillStyle = "rgba(255,0,0, 1)";
2329 } else {
2330 ctx.strokeStyle = "rgba(0,0,255, 1)";
2331 ctx.fillStyle = "rgba(0,0,255, 1)";
2332 }
2333 ctx.stroke();
2334 ctx.font = "normal 16px Arial";
2335 ctx.textAlign = "center";
2336 ctx.fillText(label, _px, _py + 5);
2337 ctx.font = "normal 10px Arial";
2338}
2339
2340function drawID(curve, id) {
2341 var px = x_at_t(curve, 0.5);
2342 var py = y_at_t(curve, 0.5);
2343 var _px = (px - srcLeft) * scale;
2344 var _py = (py - srcTop) * scale;
2345 draw_id_at(id, _px, _py);
2346}
2347
2348function draw_id_at(id, _px, _py) {
2349 ctx.beginPath();
2350 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2351 ctx.closePath();
2352 ctx.fillStyle = "white";
2353 ctx.fill();
2354 ctx.strokeStyle = "rgba(127,127,0, 1)";
2355 ctx.fillStyle = "rgba(127,127,0, 1)";
2356 ctx.stroke();
2357 ctx.font = "normal 16px Arial";
2358 ctx.textAlign = "center";
2359 ctx.fillText(id, _px, _py + 5);
2360 ctx.font = "normal 10px Arial";
2361}
2362
2363function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2364 var curve = [x1, y1, x2, y2];
2365 drawCurvePartialID(id, curve, t1, t2);
2366}
2367
2368function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2369 var curve = [x1, y1, x2, y2, x3, y3];
2370 drawCurvePartialID(id, curve, t1, t2);
2371}
2372
caryclark1049f122015-04-20 08:31:59 -07002373function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2374 var curve = [x1, y1, x2, y2, x3, y3, w];
2375 drawCurvePartialID(id, curve, t1, t2);
2376}
2377
caryclarkdac1d172014-06-17 05:15:38 -07002378function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2379 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2380 drawCurvePartialID(id, curve, t1, t2);
2381}
2382
2383function drawCurvePartialID(id, curve, t1, t2) {
2384 var px = x_at_t(curve, (t1 + t2) / 2);
2385 var py = y_at_t(curve, (t1 + t2) / 2);
2386 var _px = (px - srcLeft) * scale;
2387 var _py = (py - srcTop) * scale;
2388 draw_id_at(id, _px, _py);
2389}
2390
2391function drawCurveSpecials(test, curve, type) {
2392 if (pt_labels) {
2393 drawPoints(curve, type, pt_labels == 2);
2394 }
2395 if (control_lines != 0) {
2396 drawControlLines(curve, type, control_lines);
2397 }
2398 if (curve_t) {
2399 drawPointAtT(curve, type);
2400 }
2401 if (draw_midpoint) {
2402 var mid = pointAtT(curve, type, 0.5);
2403 drawPoint(mid.x, mid.y, true);
2404 }
2405 if (draw_id) {
2406 var id = idByCurve(test, curve, type);
2407 if (id >= 0) {
2408 drawID(curve, id);
2409 }
2410 }
2411 if (type == PATH_LINE) {
2412 return;
2413 }
2414 if (draw_deriviatives > 0) {
2415 var d = dxy_at_t(curve, type, 0);
caryclark03b03ca2015-04-23 09:13:37 -07002416 drawArrow(curve[0], curve[1], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002417 if (draw_deriviatives == 2) {
2418 d = dxy_at_t(curve, type, 1);
2419 if (type == PATH_CUBIC) {
caryclark03b03ca2015-04-23 09:13:37 -07002420 drawArrow(curve[6], curve[7], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002421 } else {
caryclark03b03ca2015-04-23 09:13:37 -07002422 drawArrow(curve[4], curve[5], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002423 }
2424 }
2425 if (draw_midpoint) {
2426 var mid = pointAtT(curve, type, 0.5);
2427 d = dxy_at_t(curve, type, 0.5);
caryclark03b03ca2015-04-23 09:13:37 -07002428 drawArrow(mid.x, mid.y, d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002429 }
2430 }
2431 if (type != PATH_CUBIC) {
2432 return;
2433 }
caryclarkdac1d172014-06-17 05:15:38 -07002434 if (draw_sequence) {
2435 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2436 for (var i = 0; i < 8; i+= 2) {
2437 drawLabelX(ymin, i >> 1, curve[i]);
2438 }
2439 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2440 for (var i = 1; i < 8; i+= 2) {
2441 drawLabelY(xmin, i >> 1, curve[i]);
2442 }
2443 }
2444}
2445
2446function logCurves(test) {
2447 for (curves in test) {
2448 var curve = test[curves];
2449 dumpCurve(curve);
2450 }
2451}
2452
2453function curveToString(curve) {
2454 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002455 var length = curve.length == 7 ? 6 : curve.length;
2456 if (curve.length == 7) {
2457 str += "{";
2458 }
2459 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002460 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2461 if (i < curve.length - 2) {
2462 str += "}, {";
2463 }
2464 }
caryclark1049f122015-04-20 08:31:59 -07002465 str += "}";
2466 if (curve.length == 7) {
2467 str += "}, " + curve[6].toFixed(decimal_places);
2468 }
2469 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07002470 return str;
2471}
2472
2473function dumpCurve(curve) {
2474 console.log(curveToString(curve));
2475}
2476
2477function draw(test, lines, title) {
2478 ctx.fillStyle = "rgba(0,0,0, 0.1)";
2479 ctx.font = "normal 50px Arial";
2480 ctx.textAlign = "left";
2481 ctx.fillText(title, 50, 50);
2482 ctx.font = "normal 10px Arial";
2483 ctx.lineWidth = "1.001"; "0.999";
2484 var secondPath = test.length;
2485 var closeCount = 0;
2486 logStart = -1;
2487 logRange = 0;
2488 // find last active rec type at this step
2489 var curType = test[0];
2490 var curStep = 0;
2491 var hasOp = false;
2492 var lastActive = 0;
2493 var lastAdd = 0;
2494 var lastSect = 0;
2495 var lastSort = 0;
2496 var lastMark = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002497 var lastTop = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002498 activeCount = 0;
2499 addCount = 0;
2500 angleCount = 0;
2501 opCount = 0;
2502 sectCount = 0;
2503 sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002504 topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002505 markCount = 0;
2506 activeMax = 0;
2507 addMax = 0;
2508 angleMax = 0;
2509 opMax = 0;
2510 sectMax = 0;
2511 sectMax2 = 0;
2512 sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002513 topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002514 markMax = 0;
2515 lastIndex = test.length - 3;
2516 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
2517 var recType = test[tIndex];
2518 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
2519 console.log("unknown rec type: " + recType);
2520 throw "stop execution";
2521 }
2522 // if (curType == recType && curType != REC_TYPE_ADD) {
2523 // continue;
2524 // }
2525 var inStepRange = step_limit == 0 || curStep < step_limit;
2526 curType = recType;
2527 if (recType == REC_TYPE_OP) {
2528 hasOp = true;
2529 continue;
2530 }
2531 if (recType == REC_TYPE_UNKNOWN) {
2532 // these types do not advance step
2533 continue;
2534 }
2535 var bumpStep = false;
2536 var records = test[tIndex + 2];
2537 var fragType = records[0];
2538 if (recType == REC_TYPE_ADD) {
2539 if (records.length != 2) {
2540 console.log("expect only two elements: " + records.length);
2541 throw "stop execution";
2542 }
2543 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
2544 continue;
2545 }
2546 ++addMax;
2547 if (!draw_add || !inStepRange) {
2548 continue;
2549 }
2550 lastAdd = tIndex;
2551 ++addCount;
2552 bumpStep = true;
2553 }
2554 if (recType == REC_TYPE_PATH && hasOp) {
2555 secondPath = tIndex;
2556 }
caryclark54359292015-03-26 07:52:43 -07002557 if (recType == REC_TYPE_PATH2 && hasOp) {
2558 secondPath = tIndex;
2559 }
caryclarkdac1d172014-06-17 05:15:38 -07002560 if (recType == REC_TYPE_ACTIVE) {
2561 ++activeMax;
2562 if (!draw_active || !inStepRange) {
2563 continue;
2564 }
2565 lastActive = tIndex;
2566 ++activeCount;
2567 bumpStep = true;
2568 }
2569 if (recType == REC_TYPE_ACTIVE_OP) {
2570 ++opMax;
2571 if (!draw_op || !inStepRange) {
2572 continue;
2573 }
2574 lastOp = tIndex;
2575 ++opCount;
2576 bumpStep = true;
2577 }
caryclark54359292015-03-26 07:52:43 -07002578 if (recType == REC_TYPE_AFTERPART) {
2579 if (draw_angle != 3 || !inStepRange) {
2580 continue;
2581 }
2582 lastAngle = tIndex;
2583 ++angleCount;
2584 bumpStep = true;
2585 }
caryclarkdac1d172014-06-17 05:15:38 -07002586 if (recType == REC_TYPE_ANGLE) {
2587 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07002588 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07002589 continue;
2590 }
2591 lastAngle = tIndex;
2592 ++angleCount;
2593 bumpStep = true;
2594 }
2595 if (recType == REC_TYPE_SECT) {
2596 if (records.length != 2) {
2597 console.log("expect only two elements: " + records.length);
2598 throw "stop execution";
2599 }
2600 ++sectMax;
2601 var sectBump = 1;
2602 switch (fragType) {
2603 case INTERSECT_LINE:
2604 case INTERSECT_QUAD_LINE:
2605 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002606 case INTERSECT_CONIC_LINE:
2607 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07002608 case INTERSECT_SELF_CUBIC:
2609 case INTERSECT_CUBIC_LINE:
2610 case INTERSECT_CUBIC_QUAD:
2611 case INTERSECT_CUBIC:
2612 sectBump = 1;
2613 break;
2614 case INTERSECT_LINE_2:
2615 case INTERSECT_QUAD_LINE_2:
2616 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07002617 case INTERSECT_CONIC_LINE_2:
2618 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07002619 case INTERSECT_CUBIC_LINE_2:
2620 case INTERSECT_CUBIC_QUAD_2:
2621 case INTERSECT_CUBIC_2:
2622 sectBump = 2;
2623 break;
2624 case INTERSECT_LINE_NO:
2625 case INTERSECT_QUAD_LINE_NO:
2626 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07002627 case INTERSECT_CONIC_LINE_NO:
2628 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07002629 case INTERSECT_SELF_CUBIC_NO:
2630 case INTERSECT_CUBIC_LINE_NO:
2631 case INTERSECT_CUBIC_QUAD_NO:
2632 case INTERSECT_CUBIC_NO:
2633 sectBump = 0;
2634 break;
2635 case INTERSECT_CUBIC_LINE_3:
2636 case INTERSECT_CUBIC_QUAD_3:
2637 case INTERSECT_CUBIC_3:
2638 sectBump = 3;
2639 break;
2640 case INTERSECT_CUBIC_QUAD_4:
2641 case INTERSECT_CUBIC_4:
2642 sectBump = 4;
2643 break;
2644 default:
2645 console.log("missing case " + records.length);
2646 throw "stop execution";
2647 }
2648 sectMax2 += sectBump;
2649 if (draw_intersection <= 1 || !inStepRange) {
2650 continue;
2651 }
2652 lastSect = tIndex;
2653 sectCount += sectBump;
2654 bumpStep = true;
2655 }
2656 if (recType == REC_TYPE_SORT) {
2657 ++sortMax;
2658 if (!draw_sort || !inStepRange) {
2659 continue;
2660 }
2661 lastSort = tIndex;
2662 ++sortCount;
2663 bumpStep = true;
2664 }
caryclark03b03ca2015-04-23 09:13:37 -07002665 if (recType == REC_TYPE_TOP) {
2666 ++topMax;
2667 if (!draw_top || !inStepRange) {
2668 continue;
2669 }
2670 lastTop = tIndex;
2671 ++topCount;
2672 bumpStep = true;
2673 }
caryclarkdac1d172014-06-17 05:15:38 -07002674 if (recType == REC_TYPE_MARK) {
2675 ++markMax;
2676 if (!draw_mark || !inStepRange) {
2677 continue;
2678 }
2679 lastMark = tIndex;
2680 ++markCount;
2681 bumpStep = true;
2682 }
2683 if (bumpStep) {
2684 lastIndex = tIndex;
2685 logStart = test[tIndex + 1];
2686 logRange = records.length / 2;
2687 ++curStep;
2688 }
2689 }
2690 stepMax = (draw_add ? addMax : 0)
2691 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07002692 + (draw_angle ? angleMax : 0)
caryclark54359292015-03-26 07:52:43 -07002693 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002694 + (draw_sort ? sortMax : 0)
caryclark03b03ca2015-04-23 09:13:37 -07002695 + (draw_top ? topMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002696 + (draw_mark ? markMax : 0)
2697 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
2698 if (stepMax == 0) {
caryclark03b03ca2015-04-23 09:13:37 -07002699 stepMax = addMax + activeMax + angleMax + opMax + sortMax + topMax + markMax;
caryclarkdac1d172014-06-17 05:15:38 -07002700 }
2701 drawnPts = [];
2702 drawnLines = [];
2703 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07002704 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07002705 drawnCubics = [];
2706 focusXmin = focusYmin = Infinity;
2707 focusXmax = focusYmax = -Infinity;
2708 var pathIndex = 0;
2709 var opLetter = 'S';
2710 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
2711 var recType = test[tIndex];
2712 var records = test[tIndex + 2];
2713 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
2714 var fragType = records[recordIndex];
2715 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
2716 console.log("unknown in range frag type: " + fragType);
2717 throw "stop execution";
2718 }
2719 var frags = records[recordIndex + 1];
2720 focus_enabled = false;
2721 switch (recType) {
2722 case REC_TYPE_COMPUTED:
2723 if (draw_computed == 0) {
2724 continue;
2725 }
2726 ctx.lineWidth = 1;
2727 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
2728 ctx.fillStyle = "blue";
2729 var drawThis = false;
2730 switch (fragType) {
2731 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002732 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
2733 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002734 drawQuad(frags[0], frags[1], frags[2], frags[3],
2735 frags[4], frags[5]);
2736 drawThis = true;
2737 }
2738 break;
caryclark1049f122015-04-20 08:31:59 -07002739 case PATH_CONIC:
2740 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
2741 && (draw_computed & 7) == pathIndex)) {
2742 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2743 frags[4], frags[5], frags[6]);
2744 drawThis = true;
2745 }
2746 break;
caryclarkdac1d172014-06-17 05:15:38 -07002747 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07002748 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
2749 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002750 drawCubic(frags[0], frags[1], frags[2], frags[3],
2751 frags[4], frags[5], frags[6], frags[7]);
2752 drawThis = true;
2753 }
2754 ++pathIndex;
2755 break;
2756 case COMPUTED_SET_1:
2757 pathIndex = 0;
2758 break;
2759 case COMPUTED_SET_2:
2760 pathIndex = 1;
2761 break;
2762 default:
2763 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
2764 throw "stop execution";
2765 }
2766 if (!drawThis || collect_bounds) {
2767 break;
2768 }
2769 drawCurveSpecials(test, frags, fragType);
2770 break;
2771 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07002772 case REC_TYPE_PATH2:
caryclarkdac1d172014-06-17 05:15:38 -07002773 if (!draw_path) {
2774 continue;
2775 }
2776 var firstPath = tIndex < secondPath;
2777 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
2778 continue;
2779 }
2780 ctx.lineWidth = 1;
2781 ctx.strokeStyle = firstPath ? "black" : "red";
2782 ctx.fillStyle = "blue";
caryclark54359292015-03-26 07:52:43 -07002783 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07002784 switch (fragType) {
2785 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07002786 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
2787 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07002788 break;
2789 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07002790 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
2791 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
2792 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07002793 break;
caryclark1049f122015-04-20 08:31:59 -07002794 case PATH_CONIC:
2795 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
2796 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
2797 frags2[4], frags2[5], frags2[6]);
2798 break;
caryclarkdac1d172014-06-17 05:15:38 -07002799 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07002800 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
2801 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
2802 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07002803 break;
2804 default:
caryclark54359292015-03-26 07:52:43 -07002805 console.log("unknown REC_TYPE_PATH2 frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002806 throw "stop execution";
2807 }
2808 if (collect_bounds) {
2809 break;
2810 }
caryclark54359292015-03-26 07:52:43 -07002811 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002812 break;
2813 case REC_TYPE_OP:
2814 switch (fragType) {
2815 case OP_INTERSECT: opLetter = 'I'; break;
2816 case OP_DIFFERENCE: opLetter = 'D'; break;
2817 case OP_UNION: opLetter = 'U'; break;
2818 case OP_XOR: opLetter = 'X'; break;
2819 default:
2820 console.log("unknown REC_TYPE_OP frag type: " + fragType);
2821 throw "stop execution";
2822 }
2823 break;
2824 case REC_TYPE_ACTIVE:
2825 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
2826 continue;
2827 }
2828 var x1 = frags[SPAN_X1];
2829 var y1 = frags[SPAN_Y1];
2830 var x2 = frags[SPAN_X2];
2831 var y2 = frags[SPAN_Y2];
caryclark1049f122015-04-20 08:31:59 -07002832 var x3, y3, x3, y4, t1, t2, w;
caryclarkdac1d172014-06-17 05:15:38 -07002833 ctx.lineWidth = 3;
2834 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2835 focus_enabled = true;
2836 switch (fragType) {
2837 case ACTIVE_LINE_SPAN:
2838 t1 = frags[SPAN_L_T];
2839 t2 = frags[SPAN_L_TEND];
2840 drawLinePartial(x1, y1, x2, y2, t1, t2);
2841 if (draw_id) {
2842 drawLinePartialID(frags[0], x1, y1, x2, y2, t1, t2);
2843 }
2844 break;
2845 case ACTIVE_QUAD_SPAN:
2846 x3 = frags[SPAN_X3];
2847 y3 = frags[SPAN_Y3];
2848 t1 = frags[SPAN_Q_T];
2849 t2 = frags[SPAN_Q_TEND];
2850 drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2851 if (draw_id) {
2852 drawQuadPartialID(frags[0], x1, y1, x2, y2, x3, y3, t1, t2);
2853 }
2854 break;
caryclark1049f122015-04-20 08:31:59 -07002855 case ACTIVE_CONIC_SPAN:
2856 x3 = frags[SPAN_X3];
2857 y3 = frags[SPAN_Y3];
2858 t1 = frags[SPAN_K_T];
2859 t2 = frags[SPAN_K_TEND];
2860 w = frags[SPAN_K_W];
2861 drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2862 if (draw_id) {
2863 drawConicPartialID(frags[0], x1, y1, x2, y2, x3, y3, w, t1, t2);
2864 }
2865 break;
caryclarkdac1d172014-06-17 05:15:38 -07002866 case ACTIVE_CUBIC_SPAN:
2867 x3 = frags[SPAN_X3];
2868 y3 = frags[SPAN_Y3];
2869 x4 = frags[SPAN_X4];
2870 y4 = frags[SPAN_Y4];
2871 t1 = frags[SPAN_C_T];
2872 t2 = frags[SPAN_C_TEND];
2873 drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2874 if (draw_id) {
2875 drawCubicPartialID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2876 }
2877 break;
2878 default:
2879 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
2880 throw "stop execution";
2881 }
2882 break;
2883 case REC_TYPE_ACTIVE_OP:
2884 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
2885 continue;
2886 }
2887 focus_enabled = true;
2888 ctx.lineWidth = 3;
2889 var activeSpan = frags[7] == "1";
2890 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
2891 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
2892 drawCurve(curve);
2893 if (draw_op > 1) {
2894 drawArc(curve, false, frags[3], frags[4]);
2895 drawArc(curve, true, frags[5], frags[6]);
2896 }
2897 break;
2898 case REC_TYPE_ADD:
2899 if (!draw_add) {
2900 continue;
2901 }
2902 ctx.lineWidth = 3;
2903 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
2904 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
2905 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
2906 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
2907 : "rgba(127,0,127, 0.3)";
2908 focus_enabled = true;
2909 switch (fragType) {
2910 case ADD_MOVETO:
2911 break;
2912 case ADD_LINETO:
2913 if (step_limit == 0 || tIndex >= lastAdd) {
2914 drawLine(frags[0], frags[1], frags[2], frags[3]);
2915 }
2916 break;
2917 case ADD_QUADTO:
2918 if (step_limit == 0 || tIndex >= lastAdd) {
2919 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
2920 }
2921 break;
caryclark1049f122015-04-20 08:31:59 -07002922 case ADD_CONICTO:
2923 if (step_limit == 0 || tIndex >= lastAdd) {
2924 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2925 frags[4], frags[5], frags[6]);
2926 }
2927 break;
caryclarkdac1d172014-06-17 05:15:38 -07002928 case ADD_CUBICTO:
2929 if (step_limit == 0 || tIndex >= lastAdd) {
2930 drawCubic(frags[0], frags[1], frags[2], frags[3],
2931 frags[4], frags[5], frags[6], frags[7]);
2932 }
2933 break;
2934 case ADD_CLOSE:
2935 ++closeCount;
2936 break;
2937 case ADD_FILL:
2938 break;
2939 default:
2940 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
2941 throw "stop execution";
2942 }
2943 break;
2944 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07002945 angleBetween = frags[18] == "T";
2946 afterIndex = 0;
2947 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07002948 continue;
2949 }
2950 focus_enabled = true;
2951 ctx.lineWidth = 3;
2952 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07002953 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
2954 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
2955 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07002956 drawCurve(leftCurve);
2957 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07002958 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07002959 drawCurve(midCurve);
2960 if (draw_angle > 1) {
2961 drawOrder(leftCurve, 'L');
2962 drawOrder(rightCurve, 'R');
2963 }
2964 break;
caryclark54359292015-03-26 07:52:43 -07002965 case REC_TYPE_AFTERPART:
2966 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
2967 continue;
2968 }
2969 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
2970 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
2971 : "rgba(0,0,255, 1.0)";
2972 switch (fragType) {
2973 case PATH_LINE:
2974 drawLine(frags[0], frags[1], frags[2], frags[3]);
2975 break;
2976 case PATH_QUAD:
2977 drawQuad(frags[0], frags[1], frags[2], frags[3],
2978 frags[4], frags[5]);
2979 break;
caryclark1049f122015-04-20 08:31:59 -07002980 case PATH_CONIC:
2981 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2982 frags[4], frags[5], frags[6]);
2983 break;
caryclark54359292015-03-26 07:52:43 -07002984 case PATH_CUBIC:
2985 drawCubic(frags[0], frags[1], frags[2], frags[3],
caryclark1049f122015-04-20 08:31:59 -07002986 frags[4], frags[5], frags[6], frags[7]);
caryclark54359292015-03-26 07:52:43 -07002987 break;
2988 default:
2989 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
2990 throw "stop execution";
2991 }
2992 ++afterIndex;
2993 break;
caryclarkdac1d172014-06-17 05:15:38 -07002994 case REC_TYPE_SECT:
2995 if (!draw_intersection) {
2996 continue;
2997 }
2998 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
2999 continue;
3000 }
3001 // draw_intersection == 1 : show all
3002 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
3003 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
3004 ctx.lineWidth = 1;
3005 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3006 ctx.fillStyle = "blue";
3007 focus_enabled = true;
3008 var f = [];
3009 var c1s;
3010 var c1l;
3011 var c2s;
3012 var c2l;
3013 switch (fragType) {
3014 case INTERSECT_LINE:
3015 f.push(5, 6, 0, 7);
3016 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
3017 break;
3018 case INTERSECT_LINE_2:
3019 f.push(5, 6, 0, 10);
3020 f.push(8, 9, 7, 15);
3021 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
3022 break;
3023 case INTERSECT_LINE_NO:
3024 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
3025 break;
3026 case INTERSECT_QUAD_LINE:
3027 f.push(7, 8, 0, 9);
3028 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
3029 break;
3030 case INTERSECT_QUAD_LINE_2:
3031 f.push(7, 8, 0, 12);
3032 f.push(10, 11, 9, 17);
3033 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
3034 break;
3035 case INTERSECT_QUAD_LINE_NO:
3036 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
3037 break;
3038 case INTERSECT_QUAD:
3039 f.push(7, 8, 0, 9);
3040 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
3041 break;
3042 case INTERSECT_QUAD_2:
3043 f.push(7, 8, 0, 12);
3044 f.push(10, 11, 9, 19);
3045 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
3046 break;
3047 case INTERSECT_QUAD_NO:
3048 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
3049 break;
caryclark1049f122015-04-20 08:31:59 -07003050 case INTERSECT_CONIC_LINE:
3051 f.push(8, 9, 0, 10);
3052 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
3053 break;
3054 case INTERSECT_CONIC_LINE_2:
3055 f.push(8, 9, 0, 12);
3056 f.push(11, 12, 10, 18);
3057 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
3058 break;
3059 case INTERSECT_CONIC_LINE_NO:
3060 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
3061 break;
3062 case INTERSECT_CONIC:
3063 f.push(8, 9, 0, 10);
3064 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
3065 break;
3066 case INTERSECT_CONIC_2:
3067 f.push(8, 9, 0, 13);
3068 f.push(11, 12, 10, 21);
3069 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
3070 break;
3071 case INTERSECT_CONIC_NO:
3072 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
3073 break;
caryclarkdac1d172014-06-17 05:15:38 -07003074 case INTERSECT_SELF_CUBIC:
3075 f.push(9, 10, 0, 11);
3076 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
3077 break;
3078 case INTERSECT_SELF_CUBIC_NO:
3079 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
3080 break;
3081 case INTERSECT_CUBIC_LINE:
3082 f.push(9, 10, 0, 11);
3083 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3084 break;
3085 case INTERSECT_CUBIC_LINE_2:
3086 f.push(9, 10, 0, 14);
3087 f.push(12, 13, 11, 19);
3088 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3089 break;
3090 case INTERSECT_CUBIC_LINE_3:
3091 f.push(9, 10, 0, 17);
3092 f.push(12, 13, 11, 22);
3093 f.push(15, 16, 14, 23);
3094 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3095 break;
3096 case INTERSECT_CUBIC_QUAD_NO:
3097 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3098 break;
3099 case INTERSECT_CUBIC_QUAD:
3100 f.push(9, 10, 0, 11);
3101 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3102 break;
3103 case INTERSECT_CUBIC_QUAD_2:
3104 f.push(9, 10, 0, 14);
3105 f.push(12, 13, 11, 21);
3106 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3107 break;
3108 case INTERSECT_CUBIC_QUAD_3:
3109 f.push(9, 10, 0, 17);
3110 f.push(12, 13, 11, 24);
3111 f.push(15, 16, 14, 25);
3112 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3113 break;
3114 case INTERSECT_CUBIC_QUAD_4:
3115 f.push(9, 10, 0, 20);
3116 f.push(12, 13, 11, 27);
3117 f.push(15, 16, 14, 28);
3118 f.push(18, 19, 17, 29);
3119 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3120 break;
3121 case INTERSECT_CUBIC_LINE_NO:
3122 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3123 break;
3124 case INTERSECT_CUBIC:
3125 f.push(9, 10, 0, 11);
3126 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3127 break;
3128 case INTERSECT_CUBIC_2:
3129 f.push(9, 10, 0, 14);
3130 f.push(12, 13, 11, 23);
3131 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3132 break;
3133 case INTERSECT_CUBIC_3:
3134 f.push(9, 10, 0, 17);
3135 f.push(12, 13, 11, 26);
3136 f.push(15, 16, 14, 27);
3137 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3138 break;
3139 case INTERSECT_CUBIC_4:
3140 f.push(9, 10, 0, 20);
3141 f.push(12, 13, 11, 29);
3142 f.push(15, 16, 14, 30);
3143 f.push(18, 19, 17, 31);
3144 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3145 break;
3146 case INTERSECT_CUBIC_NO:
3147 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3148 break;
3149 default:
3150 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3151 throw "stop execution";
3152 }
3153 if (draw_intersection != 1) {
3154 var id = -1;
3155 var curve;
3156 switch (c1l) {
3157 case 4:
3158 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3159 if (draw_id) {
3160 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3161 id = idByCurve(test, curve, PATH_LINE);
3162 }
3163 break;
3164 case 6:
3165 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3166 frags[c1s + 4], frags[c1s + 5]);
3167 if (draw_id) {
3168 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3169 frags[c1s + 4], frags[c1s + 5]];
3170 id = idByCurve(test, curve, PATH_QUAD);
3171 }
3172 break;
caryclark1049f122015-04-20 08:31:59 -07003173 case 7:
3174 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3175 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3176 if (draw_id) {
3177 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3178 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3179 id = idByCurve(test, curve, PATH_CONIC);
3180 }
3181 break;
caryclarkdac1d172014-06-17 05:15:38 -07003182 case 8:
3183 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3184 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3185 if (draw_id) {
3186 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3187 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3188 id = idByCurve(test, curve, PATH_CUBIC);
3189 }
3190 break;
3191 }
3192 if (id >= 0) {
3193 drawID(curve, id);
3194 }
3195 id = -1;
3196 switch (c2l) {
3197 case 0:
3198 break;
3199 case 4:
3200 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3201 if (draw_id) {
3202 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3203 id = idByCurve(test, curve, PATH_LINE);
3204 }
3205 break;
3206 case 6:
3207 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3208 frags[c2s + 4], frags[c2s + 5]);
3209 if (draw_id) {
3210 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3211 frags[c2s + 4], frags[c2s + 5]];
3212 id = idByCurve(test, curve, PATH_QUAD);
3213 }
3214 break;
caryclark1049f122015-04-20 08:31:59 -07003215 case 7:
3216 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3217 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3218 if (draw_id) {
3219 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3220 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3221 id = idByCurve(test, curve, PATH_CONIC);
3222 }
3223 break;
caryclarkdac1d172014-06-17 05:15:38 -07003224 case 8:
3225 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3226 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3227 if (draw_id) {
3228 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3229 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3230 id = idByCurve(test, curve, PATH_CUBIC);
3231 }
3232 break;
3233 }
3234 if (id >= 0) {
3235 drawID(curve, id);
3236 }
3237 }
3238 if (collect_bounds) {
3239 break;
3240 }
caryclark54359292015-03-26 07:52:43 -07003241 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3242 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003243 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3244 }
3245 }
3246 if (!draw_intersectT) {
3247 break;
3248 }
3249 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003250 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3251 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003252 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3253 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3254 }
3255 }
3256 break;
3257 case REC_TYPE_SORT:
3258 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3259 continue;
3260 }
3261 ctx.lineWidth = 3;
3262 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3263 focus_enabled = true;
3264 switch (fragType) {
3265 case SORT_UNARY:
3266 case SORT_BINARY:
3267 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3268 drawCurve(curve);
3269 break;
3270 default:
3271 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3272 throw "stop execution";
3273 }
3274 break;
caryclark03b03ca2015-04-23 09:13:37 -07003275 case REC_TYPE_TOP:
3276 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
3277 continue;
3278 }
3279 ctx.lineWidth = 3;
3280 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3281 focus_enabled = true;
3282 {
3283 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3284 drawCurve(curve);
3285 var type = PATH_LINE + (curve.length / 2 - 2);
3286 var mid = pointAtT(curve, type, 0.5);
3287 var d = dxy_at_t(curve, type, 0.5);
3288 drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
3289 }
3290 break;
caryclarkdac1d172014-06-17 05:15:38 -07003291 case REC_TYPE_MARK:
3292 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3293 continue;
3294 }
3295 ctx.lineWidth = 3;
3296 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3297 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3298 focus_enabled = true;
3299 switch (fragType) {
3300 case MARK_LINE:
3301 case MARK_DONE_LINE:
3302 case MARK_UNSORTABLE_LINE:
3303 case MARK_SIMPLE_LINE:
3304 case MARK_SIMPLE_DONE_LINE:
3305 case MARK_DONE_UNARY_LINE:
3306 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3307 frags[5], frags[9]);
3308 if (draw_id) {
3309 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3310 frags[5], frags[9]);
3311 }
3312 break;
3313 case MARK_QUAD:
3314 case MARK_DONE_QUAD:
3315 case MARK_UNSORTABLE_QUAD:
3316 case MARK_SIMPLE_QUAD:
3317 case MARK_SIMPLE_DONE_QUAD:
3318 case MARK_DONE_UNARY_QUAD:
3319 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3320 frags[5], frags[6], frags[7], frags[11]);
3321 if (draw_id) {
3322 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3323 frags[5], frags[6], frags[7], frags[11]);
3324 }
3325 break;
3326 case MARK_CUBIC:
3327 case MARK_DONE_CUBIC:
3328 case MARK_UNSORTABLE_CUBIC:
3329 case MARK_SIMPLE_CUBIC:
3330 case MARK_SIMPLE_DONE_CUBIC:
3331 case MARK_DONE_UNARY_CUBIC:
3332 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3333 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3334 if (draw_id) {
3335 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3336 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3337 }
3338 break;
3339 case MARK_ANGLE_LAST:
3340 // FIXME: ignored for now
3341 break;
3342 default:
3343 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3344 throw "stop execution";
3345 }
3346 break;
3347 default:
3348 continue;
3349 }
3350 }
3351 switch (recType) {
3352 case REC_TYPE_SORT:
3353 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3354 break;
3355 }
3356 var angles = []; // use tangent lines to describe arcs
3357 var windFrom = [];
3358 var windTo = [];
3359 var opp = [];
3360 var minXY = Number.MAX_VALUE;
3361 var partial;
3362 focus_enabled = true;
3363 var someUnsortable = false;
3364 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3365 var fragType = records[recordIndex];
3366 var frags = records[recordIndex + 1];
3367 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3368 (fragType == SORT_BINARY && frags[16]);
3369 someUnsortable |= unsortable;
3370 switch (fragType) {
3371 case SORT_UNARY:
3372 case SORT_BINARY:
3373 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3374 break;
3375 default:
3376 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3377 throw "stop execution";
3378 }
3379 var dx = boundsWidth(partial);
3380 var dy = boundsHeight(partial);
3381 minXY = Math.min(minXY, dx * dx + dy * dy);
3382 if (collect_bounds) {
3383 continue;
3384 }
3385 angles.push(tangent(partial));
3386 var from = frags[12];
3387 var to = frags[12];
3388 var sgn = frags[10];
3389 if (sgn < 0) {
3390 from -= frags[11];
3391 } else if (sgn > 0) {
3392 to -= frags[11];
3393 }
3394 windFrom.push(from + (unsortable ? "!" : ""));
3395 windTo.push(to + (unsortable ? "!" : ""));
3396 opp.push(fragType == SORT_BINARY);
3397 if (draw_sort == 1) {
3398 drawOrder(partial, frags[12]);
3399 } else {
3400 drawOrder(partial, (recordIndex / 2) + 1);
3401 }
3402 }
3403 var radius = Math.sqrt(minXY) / 2 * scale;
3404 radius = Math.min(50, radius);
3405 var scaledRadius = radius / scale;
3406 var centerX = partial[0];
3407 var centerY = partial[1];
3408 if (collect_bounds) {
3409 if (focus_enabled) {
3410 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
3411 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
3412 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
3413 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
3414 }
3415 break;
3416 }
3417 break;
3418 default:
3419 break;
3420 }
3421 }
3422 if (collect_bounds) {
3423 return;
3424 }
3425 if (draw_log && logStart >= 0) {
3426 ctx.font = "normal 10px Arial";
3427 ctx.textAlign = "left";
3428 ctx.beginPath();
3429 var top = screenHeight - 20 - (logRange + 2) * 10;
3430 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
3431 ctx.fillStyle = "white";
3432 ctx.fill();
3433 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3434 if (logStart > 0) {
3435 ctx.fillText(lines[logStart - 1], 50, top + 8);
3436 }
3437 ctx.fillStyle = "black";
3438 for (var idx = 0; idx < logRange; ++idx) {
3439 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
3440 }
3441 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3442 if (logStart + logRange < lines.length) {
3443 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
3444 }
3445 }
3446 if (draw_legend) {
3447 var pos = 0;
caryclark54359292015-03-26 07:52:43 -07003448 var drawSomething = draw_add | draw_active | draw_angle | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07003449 // drawBox(pos++, "yellow", "black", opLetter, true, '');
3450 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
3451 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
3452 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
3453 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
3454 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
3455 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
caryclark03b03ca2015-04-23 09:13:37 -07003456 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
caryclarkdac1d172014-06-17 05:15:38 -07003457 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
3458 drawBox(pos++, "black", "white",
3459 (new Array('P', 'P1', 'P2', 'P'))[draw_path], draw_path != 0, pathKey);
3460 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
3461 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
3462 draw_computed != 0, computedKey);
3463 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
3464 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
3465 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
3466 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
3467 if (curve_t) {
3468 drawCurveTControl();
3469 }
3470 ctx.font = "normal 20px Arial";
3471 ctx.fillStyle = "rgba(0,0,0, 0.3)";
3472 ctx.textAlign = "right";
3473 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
3474 }
3475 if (draw_hints) {
3476 ctx.font = "normal 10px Arial";
3477 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3478 ctx.textAlign = "right";
3479 var y = 4;
3480 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
3481 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
3482 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
3483 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07003484 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
3485 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
3486 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
3487 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
3488 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
3489 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
3490 }
3491}
3492
3493function drawBox(y, backC, foreC, str, enable, label) {
3494 ctx.beginPath();
3495 ctx.fillStyle = backC;
3496 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
3497 ctx.fill();
3498 ctx.font = "normal 16px Arial";
3499 ctx.fillStyle = foreC;
3500 ctx.textAlign = "center";
3501 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
3502 if (!enable) {
3503 ctx.fillStyle = "rgba(255,255,255, 0.5)";
3504 ctx.fill();
3505 }
3506 if (label != '') {
3507 ctx.font = "normal 9px Arial";
3508 ctx.fillStyle = "black";
3509 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
3510 }
3511}
3512
3513function drawCurveTControl() {
3514 ctx.lineWidth = 2;
3515 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
3516 ctx.beginPath();
3517 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
3518 ctx.stroke();
3519 var ty = 40 + curveT * (screenHeight - 80);
3520 ctx.beginPath();
3521 ctx.moveTo(screenWidth - 80, ty);
3522 ctx.lineTo(screenWidth - 85, ty - 5);
3523 ctx.lineTo(screenWidth - 85, ty + 5);
3524 ctx.lineTo(screenWidth - 80, ty);
3525 ctx.fillStyle = "rgba(0,0,0, 0.6)";
3526 ctx.fill();
3527 var num = curveT.toFixed(decimal_places);
3528 ctx.font = "normal 10px Arial";
3529 ctx.textAlign = "left";
3530 ctx.fillText(num, screenWidth - 78, ty);
3531}
3532
3533function ptInTControl() {
3534 var e = window.event;
3535 var tgt = e.target || e.srcElement;
3536 var left = tgt.offsetLeft;
3537 var top = tgt.offsetTop;
3538 var x = (e.clientX - left);
3539 var y = (e.clientY - top);
3540 if (x < screenWidth - 80 || x > screenWidth - 50) {
3541 return false;
3542 }
3543 if (y < 40 || y > screenHeight - 80) {
3544 return false;
3545 }
3546 curveT = (y - 40) / (screenHeight - 120);
3547 if (curveT < 0 || curveT > 1) {
3548 throw "stop execution";
3549 }
3550 return true;
3551}
3552
3553function drawTop() {
3554 if (tests[testIndex] == null) {
3555 var str = testDivs[testIndex].textContent;
3556 parse_all(str);
3557 var title = testDivs[testIndex].id.toString();
3558 testTitles[testIndex] = title;
3559 }
3560 init(tests[testIndex]);
3561 redraw();
3562}
3563
3564function redraw() {
3565 if (focus_on_selection) {
3566 collect_bounds = true;
3567 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3568 collect_bounds = false;
3569 if (focusXmin < focusXmax && focusYmin < focusYmax) {
3570 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
3571 }
3572 }
3573 ctx.beginPath();
3574 ctx.fillStyle = "white";
3575 ctx.rect(0, 0, screenWidth, screenHeight);
3576 ctx.fill();
3577 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3578}
3579
3580function dumpCurvePartial(test, id, t0, t1) {
3581 var curve = curveByID(test, id);
3582 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
3583 console.log("id=" + id + " " + name + "=" + curveToString(curve)
3584 + " t0=" + t0 + " t1=" + t1
3585 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
3586}
3587
3588function dumpAngleTest(test, id, t0, t1) {
3589 var curve = curveByID(test, id);
3590 console.log(" { {" + curveToString(curve) + "}, "
3591 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
3592}
3593
3594function dumpLogToConsole() {
3595 if (logStart < 0) {
3596 return;
3597 }
3598 var test = tests[testIndex];
3599 var recType = REC_TYPE_UNKNOWN;
3600 var records;
3601 for (var index = 0; index < test.length; index += 3) {
3602 var lastLineNo = test[index + 1];
3603 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
3604 recType = test[index];
3605 records = test[index + 2];
3606 break;
3607 }
3608 }
3609 if (recType == REC_TYPE_UNKNOWN) {
3610 return;
3611 }
3612 var lines = testLines[testIndex];
3613 for (var idx = 0; idx < logRange; ++idx) {
3614 var line = lines[logStart + idx];
3615 console.log(line);
3616 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3617 var fragType = records[recordIndex];
3618 var frags = records[recordIndex + 1];
3619 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07003620 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
3621 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
3622 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
3623 console.log("\nstatic IntersectData intersectDataSet[] = { //");
3624 dumpAngleTest(test, frags[0], frags[4], frags[5]);
3625 dumpAngleTest(test, frags[6], frags[10], frags[11]);
3626 dumpAngleTest(test, frags[12], frags[16], frags[17]);
3627 console.log("}; //");
3628 }
3629 }
3630 }
3631}
3632
3633var activeKey = 'a';
3634var pathKey = 'b';
3635var pathBackKey = 'B';
3636var centerKey = 'c';
3637var addKey = 'd';
3638var deriviativesKey = 'f';
3639var angleKey = 'g';
3640var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07003641var intersectionKey = 'i';
3642var intersectionBackKey = 'I';
3643var sequenceKey = 'j';
3644var midpointKey = 'k';
3645var logKey = 'l';
3646var logToConsoleKey = 'L';
3647var markKey = 'm';
3648var sortKey = 'o';
3649var opKey = 'p';
3650var opBackKey = 'P';
3651var computedKey = 'q';
3652var computedBackKey = 'Q';
3653var stepKey = 's';
3654var stepBackKey = 'S';
3655var intersectTKey = 't';
caryclark03b03ca2015-04-23 09:13:37 -07003656var topKey = 'T';
caryclarkdac1d172014-06-17 05:15:38 -07003657var curveTKey = 'u';
3658var controlLinesBackKey = 'V';
3659var controlLinesKey = 'v';
3660var ptsKey = 'x';
3661var xyKey = 'y';
3662var logCurvesKey = 'z';
3663var focusKey = '`';
3664var idKey = '.';
3665var retinaKey = '\\';
3666
3667function doKeyPress(evt) {
3668 var char = String.fromCharCode(evt.charCode);
3669 var focusWasOn = false;
3670 switch (char) {
3671 case '0':
3672 case '1':
3673 case '2':
3674 case '3':
3675 case '4':
3676 case '5':
3677 case '6':
3678 case '7':
3679 case '8':
3680 case '9':
3681 decimal_places = char - '0';
3682 redraw();
3683 break;
3684 case activeKey:
3685 draw_active ^= true;
3686 redraw();
3687 break;
3688 case addKey:
3689 draw_add ^= true;
3690 redraw();
3691 break;
3692 case angleKey:
caryclark54359292015-03-26 07:52:43 -07003693 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07003694 redraw();
3695 break;
3696 case angleBackKey:
3697 draw_angle = (draw_angle + 2) % 3;
3698 redraw();
3699 break;
3700 case centerKey:
3701 setScale(xmin, xmax, ymin, ymax);
3702 redraw();
3703 break;
3704 case controlLinesBackKey:
3705 control_lines = (control_lines + 3) % 4;
3706 redraw();
3707 break;
3708 case controlLinesKey:
3709 control_lines = (control_lines + 1) % 4;
3710 redraw();
3711 break;
3712 case computedBackKey:
3713 draw_computed = (draw_computed + 5) % 6;
3714 redraw();
3715 break;
3716 case computedKey:
3717 draw_computed = (draw_computed + 1) % 6;
3718 redraw();
3719 break;
3720 case curveTKey:
3721 curve_t ^= true;
3722 if (curve_t) {
3723 draw_legend = true;
3724 }
3725 redraw();
3726 break;
3727 case deriviativesKey:
3728 draw_deriviatives = (draw_deriviatives + 1) % 3;
3729 redraw();
3730 break;
3731 case focusKey:
3732 focus_on_selection ^= true;
3733 setScale(xmin, xmax, ymin, ymax);
3734 redraw();
3735 break;
caryclarkdac1d172014-06-17 05:15:38 -07003736 case idKey:
3737 draw_id ^= true;
3738 redraw();
3739 break;
3740 case intersectionBackKey:
3741 draw_intersection = (draw_intersection + 3) % 4;
3742 redraw();
3743 break;
3744 case intersectionKey:
3745 draw_intersection = (draw_intersection + 1) % 4;
3746 redraw();
3747 break;
3748 case intersectTKey:
3749 draw_intersectT ^= true;
3750 redraw();
3751 break;
3752 case logCurvesKey:
3753 logCurves(tests[testIndex]);
3754 break;
3755 case logKey:
3756 draw_log ^= true;
3757 redraw();
3758 break;
3759 case logToConsoleKey:
3760 if (draw_log) {
3761 dumpLogToConsole();
3762 }
3763 break;
3764 case markKey:
3765 draw_mark ^= true;
3766 redraw();
3767 break;
3768 case midpointKey:
3769 draw_midpoint ^= true;
3770 redraw();
3771 break;
3772 case opKey:
3773 draw_op = (draw_op + 1) % 3;
3774 redraw();
3775 break;
3776 case opBackKey:
3777 draw_op = (draw_op + 2) % 3;
3778 redraw();
3779 break;
3780 case pathKey:
3781 draw_path = (draw_path + 1) % 4;
3782 redraw();
3783 break;
3784 case pathBackKey:
3785 draw_path = (draw_path + 3) % 4;
3786 redraw();
3787 break;
3788 case ptsKey:
3789 pt_labels = (pt_labels + 1) % 3;
3790 redraw();
3791 break;
3792 case retinaKey:
3793 retina_scale ^= true;
3794 drawTop();
3795 break;
3796 case sequenceKey:
3797 draw_sequence ^= true;
3798 redraw();
3799 break;
3800 case sortKey:
3801 draw_sort = (draw_sort + 1) % 3;
3802 drawTop();
3803 break;
3804 case stepKey:
3805 step_limit++;
3806 if (step_limit > stepMax) {
3807 step_limit = stepMax;
3808 }
3809 redraw();
3810 break;
3811 case stepBackKey:
3812 step_limit--;
3813 if (step_limit < 0) {
3814 step_limit = 0;
3815 }
3816 redraw();
3817 break;
caryclark03b03ca2015-04-23 09:13:37 -07003818 case topKey:
3819 draw_top ^= true;
3820 redraw();
3821 break;
caryclarkdac1d172014-06-17 05:15:38 -07003822 case xyKey:
3823 debug_xy = (debug_xy + 1) % 3;
3824 redraw();
3825 break;
3826 case '-':
3827 focusWasOn = focus_on_selection;
3828 if (focusWasOn) {
3829 focus_on_selection = false;
3830 scale /= 1.2;
3831 } else {
3832 scale /= 2;
3833 calcLeftTop();
3834 }
3835 redraw();
3836 focus_on_selection = focusWasOn;
3837 break;
3838 case '=':
3839 case '+':
3840 focusWasOn = focus_on_selection;
3841 if (focusWasOn) {
3842 focus_on_selection = false;
3843 scale *= 1.2;
3844 } else {
3845 scale *= 2;
3846 calcLeftTop();
3847 }
3848 redraw();
3849 focus_on_selection = focusWasOn;
3850 break;
3851 case '?':
3852 draw_hints ^= true;
3853 if (draw_hints && !draw_legend) {
3854 draw_legend = true;
3855 }
3856 redraw();
3857 break;
3858 case '/':
3859 draw_legend ^= true;
3860 redraw();
3861 break;
3862 }
3863}
3864
3865function doKeyDown(evt) {
3866 var char = evt.keyCode;
3867 var preventDefault = false;
3868 switch (char) {
3869 case 37: // left arrow
3870 if (evt.shiftKey) {
3871 testIndex -= 9;
3872 }
3873 if (--testIndex < 0)
3874 testIndex = tests.length - 1;
3875 drawTop();
3876 preventDefault = true;
3877 break;
3878 case 39: // right arrow
3879 if (evt.shiftKey) {
3880 testIndex += 9;
3881 }
3882 if (++testIndex >= tests.length)
3883 testIndex = 0;
3884 drawTop();
3885 preventDefault = true;
3886 break;
3887 }
3888 if (preventDefault) {
3889 evt.preventDefault();
3890 return false;
3891 }
3892 return true;
3893}
3894
3895(function() {
3896 var hidden = "hidden";
3897
3898 // Standards:
3899 if (hidden in document)
3900 document.addEventListener("visibilitychange", onchange);
3901 else if ((hidden = "mozHidden") in document)
3902 document.addEventListener("mozvisibilitychange", onchange);
3903 else if ((hidden = "webkitHidden") in document)
3904 document.addEventListener("webkitvisibilitychange", onchange);
3905 else if ((hidden = "msHidden") in document)
3906 document.addEventListener("msvisibilitychange", onchange);
3907 // IE 9 and lower:
3908 else if ('onfocusin' in document)
3909 document.onfocusin = document.onfocusout = onchange;
3910 // All others:
3911 else
3912 window.onpageshow = window.onpagehide
3913 = window.onfocus = window.onblur = onchange;
3914
3915 function onchange (evt) {
3916 var v = 'visible', h = 'hidden',
3917 evtMap = {
3918 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
3919 };
3920
3921 evt = evt || window.event;
3922 if (evt.type in evtMap)
3923 document.body.className = evtMap[evt.type];
3924 else
3925 document.body.className = this[hidden] ? "hidden" : "visible";
3926 }
3927})();
3928
3929function calcXY() {
3930 var e = window.event;
3931 var tgt = e.target || e.srcElement;
3932 var left = tgt.offsetLeft;
3933 var top = tgt.offsetTop;
3934 mouseX = (e.clientX - left) / scale + srcLeft;
3935 mouseY = (e.clientY - top) / scale + srcTop;
3936}
3937
3938function calcLeftTop() {
3939 srcLeft = mouseX - screenWidth / 2 / scale;
3940 srcTop = mouseY - screenHeight / 2 / scale;
3941}
3942
3943var disableClick = false;
3944
3945function handleMouseClick() {
3946 if (disableClick) {
3947 return;
3948 }
3949 if (!curve_t || !ptInTControl()) {
3950 calcXY();
3951 calcLeftTop();
3952 }
3953 redraw();
3954// if (!curve_t || !ptInTControl()) {
3955// mouseX = screenWidth / 2 / scale + srcLeft;
3956// mouseY = screenHeight / 2 / scale + srcTop;
3957// }
3958}
3959
3960function handleMouseOver() {
3961 calcXY();
3962 if (debug_xy != 2) {
3963 return;
3964 }
3965 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
3966 ctx.beginPath();
3967 ctx.rect(300,100,num.length * 6,10);
3968 ctx.fillStyle="white";
3969 ctx.fill();
3970 ctx.font = "normal 10px Arial";
3971 ctx.fillStyle="black";
3972 ctx.textAlign = "left";
3973 ctx.fillText(num, 300, 108);
3974}
3975
3976function start() {
3977 for (var i = 0; i < testDivs.length; ++i) {
3978 tests[i] = null;
3979 }
3980 testIndex = 0;
3981 drawTop();
3982 window.addEventListener('keypress', doKeyPress, true);
3983 window.addEventListener('keydown', doKeyDown, true);
3984 window.onresize = function() {
3985 drawTop();
3986 }
3987 /*
3988 window.onpagehide = function() {
3989 disableClick = true;
3990 }
3991 */
3992 window.onpageshow = function () {
3993 disableClick = false;
3994 }
3995}
3996
3997</script>
3998</head>
3999
4000<body onLoad="start();">
4001<canvas id="canvas" width="750" height="500"
4002 onmousemove="handleMouseOver()"
4003 onclick="handleMouseClick()"
4004 ></canvas >
4005</body>
4006</html>