blob: 8f939313ab78020d9cfd86a66d1ddf7e50c909b1 [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
caryclark624637c2015-05-11 07:21:27 -07005<div id="cubics45u_release">
6seg=-1 {{{1, 3}, {1.84861219f, 5.54583645f}, {3.41736698f, 3.77081728f}, {4.48402119f, 2.56391668f}}}
7seg=-1 {{{4.48402119f, 2.56391668f}, {4.67430639f, 2.34861207f}, {4.84861231f, 2.15138769f}, {5, 2}}}
8seg=-1 {{{5, 2}, {1, 3}}}
9op union
10seg=-1 {{{3, 4}, {2.61882615f, 4.38117361f}, {2.52823925f, 4.03588009f}, {2.7282393f, 3.51794004f}}}
11seg=-1 {{{2.7282393f, 3.51794004f}, {3.05293441f, 2.67707705f}, {4.14352131f, 1.38117373f}, {6, 2}}}
12seg=-1 {{{6, 2}, {3, 4}}}
13debugShowCubicIntersection wtTs[0]=1 {{{3,4}, {2.61882615,4.38117361}, {2.52823925,4.03588009}, {2.7282393,3.51794004}}} {{2.7282393,3.51794004}} wnTs[0]=0 {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}}
14debugShowCubicLineIntersection wtTs[0]=0 {{{3,4}, {2.61882615,4.38117361}, {2.52823925,4.03588009}, {2.7282393,3.51794004}}} {{3,4}} wnTs[0]=1 {{{6,2}, {3,4}}}
15debugShowCubicLineIntersection wtTs[0]=1 {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{6,2}} wnTs[0]=0 {{{6,2}, {3,4}}}
16debugShowCubicIntersection wtTs[0]=0 {{{3,4}, {2.61882615,4.38117361}, {2.52823925,4.03588009}, {2.7282393,3.51794004}}} {{3,4}} wtTs[1]=0.322114632 {{2.72210693,4.16072464}} wnTs[0]=0.589197 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} wnTs[1]=0.516302729
17SkOpSegment::addT insert t=0.589197265 segID=-1 spanID=-1
18SkOpSegment::addT insert t=0.322114632 segID=-1 spanID=-1
19SkOpSegment::addT insert t=0.516302729 segID=-1 spanID=-1
20debugShowCubicIntersection no intersect {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}}
21debugShowCubicIntersection no intersect {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}}
22debugShowCubicLineIntersection wtTs[0]=0.437504678 {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{3.5942049,2.35144877}} wnTs[0]=0.351449 {{{5,2}, {1,3}}}
23SkOpSegment::addT insert t=0.437504678 segID=-1 spanID=-1
24SkOpSegment::addT insert t=0.351448746 segID=-1 spanID=-1
25debugShowCubicLineIntersection wtTs[0]=0.589250227 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} {{3.00020218,3.99986529}} wnTs[0]=0.999933 {{{6,2}, {3,4}}}
26SkOpSegment::addT insert t=0.999932596 segID=-1 spanID=-1
27SkOpSegment::addT insert t=0.589250227 segID=-1 spanID=-1
28debugShowCubicLineIntersection no intersect {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}} {{{6,2}, {3,4}}}
29debugShowLineIntersection no intersect {{{6,2}, {3,4}}} {{{5,2}, {1,3}}}
30debugShowCubicIntersection wtTs[0]=1 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} {{4.48402119,2.56391668}} wnTs[0]=0 {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}}
31debugShowCubicLineIntersection wtTs[0]=0 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} {{1,3}} wnTs[0]=1 {{{5,2}, {1,3}}}
32debugShowCubicLineIntersection wtTs[0]=1 {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}} {{5,2}} wnTs[0]=0 {{{5,2}, {1,3}}}
33SkOpSegment::sortAngles [-1] tStart=0 [-1]
34SkOpAngle::after [-1/-1] 18/17 tStart=0 tEnd=0.322114632 < [-1/-1] 1/1 tStart=0.589197265 tEnd=0.589250227 < [-1/-1] 17/17 tStart=0.589197265 tEnd=0.516302729 T 5
35SkOpAngle::afterPart {{{3,4}, {2.87721833,4.1227816}, {2.78458726,4.17018661}, {2.72210693,4.16072464}}} id=-1
36SkOpAngle::afterPart {{{3,4}, {3.00006742,3.99995506}, {3.00013476,3.99991025}, {3.00020218,3.99986529}}} id=-1
37SkOpAngle::afterPart {{{3,4}, {2.9072112,4.06185918}, {2.81442231,4.11606536}, {2.72210693,4.16072464}}} id=-1
38SkOpAngle::after [-1/-1] 18/17 tStart=0 tEnd=0.322114632 < [-1/-1] 1/1 tStart=1 tEnd=0.999932596 < [-1/-1] 1/1 tStart=0.589197265 tEnd=0.589250227 F 11
39SkOpAngle::afterPart {{{3,4}, {2.87721833,4.1227816}, {2.78458726,4.17018661}, {2.72210693,4.16072464}}} id=-1
40SkOpAngle::afterPart {{{3,4}, {3.00020218,3.99986529}}} id=-1
41SkOpAngle::afterPart {{{3,4}, {3.00006742,3.99995506}, {3.00013476,3.99991025}, {3.00020218,3.99986529}}} id=-1
42SkOpAngle::after [-1/-1] 1/1 tStart=0.589197265 tEnd=0.589250227 < [-1/-1] 1/1 tStart=1 tEnd=0.999932596 < [-1/-1] 17/17 tStart=0.589197265 tEnd=0.516302729 T 12
43SkOpAngle::afterPart {{{3,4}, {3.00006742,3.99995506}, {3.00013476,3.99991025}, {3.00020218,3.99986529}}} id=-1
44SkOpAngle::afterPart {{{3,4}, {3.00020218,3.99986529}}} id=-1
45SkOpAngle::afterPart {{{3,4}, {2.9072112,4.06185918}, {2.81442231,4.11606536}, {2.72210693,4.16072464}}} id=-1
46SkOpSegment::sortAngles [-1] tStart=0.322114632 [-1]
47SkOpAngle::after [-1/-1] 29/1 tStart=0.322114632 tEnd=0 < [-1/-1] 17/13 tStart=0.516302729 tEnd=0 < [-1/-1] 13/5 tStart=0.322114632 tEnd=1 F 11
48SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.78458726,4.17018661}, {2.87721833,4.1227816}, {3,4}}} id=-1
49SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.06824885,4.47704065}, {1.43814079,4.31442231}, {1,3}}} id=-1
50SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.59061803,4.14081206}, {2.59266219,3.86904402}, {2.7282393,3.51794004}}} id=-1
51SkOpAngle::after [-1/-1] 29/1 tStart=0.322114632 tEnd=0 < [-1/-1] 1/1 tStart=0.516302729 tEnd=0.589197265 < [-1/-1] 13/5 tStart=0.322114632 tEnd=1 T 12
52SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.78458726,4.17018661}, {2.87721833,4.1227816}, {3,4}}} id=-1
53SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.81442231,4.11606536}, {2.9072112,4.06185918}, {3,4}}} id=-1
54SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.59061803,4.14081206}, {2.59266219,3.86904402}, {2.7282393,3.51794004}}} id=-1
55SkOpSegment::sortAngles [-1] tStart=0.437504678 [-1]
56SkOpAngle::after [-1/-1] 17/21 tStart=0.437504678 tEnd=0 < [-1/-1] 1/1 tStart=0.351448746 tEnd=0 < [-1/-1] 1/1 tStart=0.437504678 tEnd=1 T 11
57SkOpAngle::afterPart {{{3.5942049,2.35144877}, {3.15895005,2.69507766}, {2.87029493,3.15005855}, {2.7282393,3.51794004}}} id=-1
58SkOpAngle::afterPart {{{3.5942049,2.35144877}, {5,2}}} id=-1
59SkOpAngle::afterPart {{{3.5942049,2.35144877}, {4.15380764,1.9096486}, {4.95573942,1.65191312}, {6,2}}} id=-1
60SkOpAngle::after [-1/-1] 17/21 tStart=0.437504678 tEnd=0 < [-1/-1] 17/17 tStart=0.351448746 tEnd=1 < [-1/-1] 1/1 tStart=0.351448746 tEnd=0 F 12
61SkOpAngle::afterPart {{{3.5942049,2.35144877}, {3.15895005,2.69507766}, {2.87029493,3.15005855}, {2.7282393,3.51794004}}} id=-1
62SkOpAngle::afterPart {{{3.5942049,2.35144877}, {1,3}}} id=-1
63SkOpAngle::afterPart {{{3.5942049,2.35144877}, {5,2}}} id=-1
64SkOpAngle::after [-1/-1] 1/1 tStart=0.351448746 tEnd=0 < [-1/-1] 17/17 tStart=0.351448746 tEnd=1 < [-1/-1] 1/1 tStart=0.437504678 tEnd=1 F 5
65SkOpAngle::afterPart {{{3.5942049,2.35144877}, {5,2}}} id=-1
66SkOpAngle::afterPart {{{3.5942049,2.35144877}, {1,3}}} id=-1
67SkOpAngle::afterPart {{{3.5942049,2.35144877}, {4.15380764,1.9096486}, {4.95573942,1.65191312}, {6,2}}} id=-1
68SkOpAngle::after [-1/-1] 1/1 tStart=0.437504678 tEnd=1 < [-1/-1] 17/17 tStart=0.351448746 tEnd=1 < [-1/-1] 17/21 tStart=0.437504678 tEnd=0 T 11
69SkOpAngle::afterPart {{{3.5942049,2.35144877}, {4.15380764,1.9096486}, {4.95573942,1.65191312}, {6,2}}} id=-1
70SkOpAngle::afterPart {{{3.5942049,2.35144877}, {1,3}}} id=-1
71SkOpAngle::afterPart {{{3.5942049,2.35144877}, {3.15895005,2.69507766}, {2.87029493,3.15005855}, {2.7282393,3.51794004}}} id=-1
72SkOpSegment::sortAngles [-1] tStart=0.999932596 [-1]
73SkOpAngle::after [-1/-1] 1/1 tStart=0.999932596 tEnd=0 < [-1/-1] 17/17 tStart=0.589250227 tEnd=0.589197265 < [-1/-1] 17/17 tStart=0.999932596 tEnd=1 T 11
74SkOpAngle::afterPart {{{3.00020218,3.99986529}, {6,2}}} id=-1
75SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3.00013476,3.99991025}, {3.00006742,3.99995506}, {3,4}}} id=-1
76SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3,4}}} id=-1
77SkOpAngle::after [-1/-1] 1/1 tStart=0.999932596 tEnd=0 < [-1/-1] 1/1 tStart=0.589250227 tEnd=1 < [-1/-1] 17/17 tStart=0.589250227 tEnd=0.589197265 T 12
78SkOpAngle::afterPart {{{3.00020218,3.99986529}, {6,2}}} id=-1
79SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3.52305312,3.65123542}, {4.04589321,3.05965083}, {4.48402119,2.56391668}}} id=-1
80SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3.00013476,3.99991025}, {3.00006742,3.99995506}, {3,4}}} id=-1
81SkOpSegment::sortAngles [-1] tStart=1 [-1]
82SkOpSegment::sortAngles [-1] tStart=0.516302729 [-1]
83SkOpSegment::sortAngles [-1] tStart=0.589197265 [-1]
84SkOpSegment::sortAngles [-1] tStart=0.589250227 [-1]
85SkOpSegment::sortAngles [-1] tStart=0.351448746 [-1]
86SkOpSegment::debugShowActiveSpans id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 (3,4) tEnd=0.322114632 windSum=? windValue=1
87SkOpSegment::debugShowActiveSpans id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 (2.72210693,4.16072464) tEnd=1 windSum=? windValue=1
88SkOpSegment::debugShowActiveSpans id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 (2.7282393,3.51794004) tEnd=0.437504678 windSum=? windValue=1
89SkOpSegment::debugShowActiveSpans id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 (3.5942049,2.35144877) tEnd=1 windSum=? windValue=1
90SkOpSegment::debugShowActiveSpans id=-1 (6,2 3,4) t=0 (6,2) tEnd=0.999932596 windSum=? windValue=1
91SkOpSegment::debugShowActiveSpans id=-1 (6,2 3,4) t=0.999932596 (3.00020218,3.99986529) tEnd=1 windSum=? windValue=1
92SkOpSegment::debugShowActiveSpans id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 (1,3) tEnd=0.516302729 windSum=? windValue=1
93SkOpSegment::debugShowActiveSpans id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 (2.72210693,4.16072464) tEnd=0.589197265 windSum=? windValue=1
94SkOpSegment::debugShowActiveSpans id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589197265 (3,4) tEnd=0.589250227 windSum=? windValue=1
95SkOpSegment::debugShowActiveSpans id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 (3.00020218,3.99986529) tEnd=1 windSum=? windValue=1
96SkOpSegment::debugShowActiveSpans id=-1 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 (4.48402119,2.56391668) tEnd=1 windSum=? windValue=1
97SkOpSegment::debugShowActiveSpans id=-1 (5,2 1,3) t=0 (5,2) tEnd=0.351448746 windSum=? windValue=1
98SkOpSegment::debugShowActiveSpans id=-1 (5,2 1,3) t=0.351448746 (3.5942049,2.35144877) tEnd=1 windSum=? windValue=1
99SkOpSpan::sortableTop dir=kTop seg=-1 t=0.161057316 pt=(2.83844042,4.12995338)
100SkOpSpan::sortableTop [0] valid=1 operand=0 span=-1 ccw=0 seg=-1 {{{5, 2}, {1, 3}}} t=0.540389895 pt=(2.83844042,2.54039001) slope=(-4,1)
101SkOpSpan::sortableTop [1] valid=1 operand=1 span=-1 ccw=1 seg=-1 {{{2.7282393f, 3.51794004f}, {3.05293441f, 2.67707705f}, {4.14352131f, 1.38117373f}, {6, 2}}} t=0.0928134153 pt=(2.83844042,3.27394509) slope=(1.40059553,-2.71475011)
102SkOpSpan::sortableTop [2] valid=1 operand=0 span=-1 ccw=1 seg=-1 {{{1, 3}, {1.84861219f, 5.54583645f}, {3.41736698f, 3.77081728f}, {4.48402119f, 2.56391668f}}} t=0.546866125 pt=(2.83844042,4.09965467) slope=(3.81218461,-2.15374068)
103SkOpSpan::sortableTop [3] valid=1 operand=1 span=-1 ccw=0 seg=-1 {{{3, 4}, {2.61882615f, 4.38117361f}, {2.52823925f, 4.03588009f}, {2.7282393f, 3.51794004f}}} t=0.161057316 pt=(2.83844042,4.12995338) slope=(-0.862714624,0.484601174)
104SkOpSegment::markWinding id=-1 (5,2 1,3) t=0.351448746 [-1] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
105SkOpSegment::markWinding id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 [-1] (1,3) tEnd=0.516302729 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
106SkOpSegment::markWinding id=-1 (5,2 1,3) t=0.351448746 [-1] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
107SkOpSegment::markWinding id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 [-1] (2.7282393,3.51794004) tEnd=0.437504678 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
108SkOpSegment::markWinding id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 [-1] (2.7282393,3.51794004) tEnd=0.437504678 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
109SkOpSegment::markWinding id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 [-1] (2.72210693,4.16072464) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
110SkOpSegment::markWinding id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 [-1] (2.72210693,4.16072464) tEnd=0.589197265 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
111SkOpSegment::markWinding id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 [-1] (2.72210693,4.16072464) tEnd=0.589197265 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
112SkOpSegment::markWinding id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 [-1] (3,4) tEnd=0.322114632 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
113SkOpSegment::markWinding id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 [-1] (3,4) tEnd=0.322114632 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
114SkOpSegment::activeOp id=-1 t=0.322114632 tEnd=0 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
115SkOpSegment::markWinding id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589197265 [-1] (3,4) tEnd=0.589250227 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
116SkOpSegment::markAngle last segment=-1 span=-1 windSum=?
117SkOpSegment::markWinding id=-1 (6,2 3,4) t=0.999932596 [-1] (3.00020218,3.99986529) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
118SkOpSegment::markAngle last segment=-1 span=-1 windSum=-1
119SkOpSegment::findNextOp
120SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=18/17 s=0 [-1] e=0.322114632 [-1] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
121SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=1/1 s=0.589197265 [-1] e=0.589250227 [-1] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
122SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=1/1 s=1 [-1] e=0.999932596 [-1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=1 operand
123SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=17/17 s=0.589197265 [-1] e=0.516302729 [-1] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-1
124SkOpSegment::activeOp id=-1 t=0.589197265 tEnd=0.589250227 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
125SkOpSegment::findNextOp chase.append segment=-1 span=-1 windSum=-2147483647
126SkOpSegment::activeOp id=-1 t=1 tEnd=0.999932596 op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
127SkOpSegment::markDone id=-1 (6,2 3,4) t=0.999932596 [-1] (3.00020218,3.99986529) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
128SkOpSegment::findNextOp chase.append segment=-1 span=-1 windSum=-1
129SkOpSegment::activeOp id=-1 t=0.589197265 tEnd=0.516302729 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
130SkOpSegment::markDone id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 [-1] (2.72210693,4.16072464) tEnd=0.589197265 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
131SkOpSegment::markDone id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 [-1] (3,4) tEnd=0.322114632 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
132SkOpSegment::findNextOp from:[-1] to:[-1] start=7083452 end=7084028
133bridgeOp current id=-1 from=(2.72210693,4.16072464) to=(3,4)
134path.moveTo(2.72210693,4.16072464);
135path.cubicTo(2.78458714,4.17018652, 2.87721825,4.12278175, 3,4);
136SkOpSegment::markDone id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589197265 [-1] (3,4) tEnd=0.589250227 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
137SkOpSegment::markWinding id=-1 (6,2 3,4) t=0 [-1] (6,2) tEnd=0.999932596 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
138SkOpSegment::markWinding id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 [-1] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
139SkOpSegment::markAngle last segment=-1 span=-1 windSum=1
140SkOpSegment::markWinding id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 [-1] (3.00020218,3.99986529) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
141SkOpSegment::markWinding id=-1 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 [-1] (4.48402119,2.56391668) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
142SkOpSegment::markWinding id=-1 (5,2 1,3) t=0 [-1] (5,2) tEnd=0.351448746 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
143SkOpSegment::markAngle last segment=-1 span=-1 windSum=1
144SkOpSegment::debugShowActiveSpans id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 (2.72210693,4.16072464) tEnd=1 windSum=-1 oppSum=1 windValue=1 oppValue=0
145SkOpSegment::debugShowActiveSpans id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 (2.7282393,3.51794004) tEnd=0.437504678 windSum=-1 oppSum=1 windValue=1 oppValue=0
146SkOpSegment::debugShowActiveSpans id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 (3.5942049,2.35144877) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
147SkOpSegment::debugShowActiveSpans id=-1 (6,2 3,4) t=0 (6,2) tEnd=0.999932596 windSum=1 oppSum=0 windValue=1 oppValue=0
148SkOpSegment::debugShowActiveSpans id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 (1,3) tEnd=0.516302729 windSum=1 oppSum=0 windValue=1 oppValue=0
149SkOpSegment::debugShowActiveSpans id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 (3.00020218,3.99986529) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
150SkOpSegment::debugShowActiveSpans id=-1 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 (4.48402119,2.56391668) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
151SkOpSegment::debugShowActiveSpans id=-1 (5,2 1,3) t=0 (5,2) tEnd=0.351448746 windSum=1 oppSum=0 windValue=1 oppValue=0
152SkOpSegment::debugShowActiveSpans id=-1 (5,2 1,3) t=0.351448746 (3.5942049,2.35144877) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
153SkOpSegment::activeOp id=-1 t=0.999932596 tEnd=0 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
caryclark03b03ca2015-04-23 09:13:37 -0700154SkOpSegment::findNextOp simple
caryclark624637c2015-05-11 07:21:27 -0700155SkOpSegment::markDone id=-1 (6,2 3,4) t=0 [-1] (6,2) tEnd=0.999932596 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
156bridgeOp current id=-1 from=(3.00020218,3.99986529) to=(6,2)
caryclark03b03ca2015-04-23 09:13:37 -0700157SkOpSegment::findNextOp
caryclark624637c2015-05-11 07:21:27 -0700158SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=1/1 s=0.437504678 [-1] e=1 [-1] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 operand
159SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=17/17 s=0.351448746 [-1] e=1 [-1] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
160SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=17/21 s=0.437504678 [-1] e=0 [-1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=1 operand
161SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=1/1 s=0.351448746 [-1] e=0 [-1] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0
162SkOpSegment::activeOp id=-1 t=0.351448746 tEnd=1 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
163SkOpSegment::markDone id=-1 (5,2 1,3) t=0.351448746 [-1] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
164SkOpSegment::markDone id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 [-1] (1,3) tEnd=0.516302729 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
165SkOpSegment::activeOp id=-1 t=0.437504678 tEnd=0 op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
166SkOpSegment::markDone id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 [-1] (2.7282393,3.51794004) tEnd=0.437504678 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
167SkOpSegment::markDone id=-1 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 [-1] (2.72210693,4.16072464) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
168SkOpSegment::activeOp id=-1 t=0.351448746 tEnd=0 op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
169SkOpSegment::markDone id=-1 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 [-1] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
170SkOpSegment::findNextOp from:[-1] to:[-1] start=7083836 end=7082508
171bridgeOp current id=-1 from=(6,2) to=(3.5942049,2.35144877)
172path.moveTo(3.00020218,3.99986529);
173path.lineTo(6,2);
174path.cubicTo(4.9557395,1.65191317, 4.15380764,1.90964866, 3.5942049,2.35144877);
caryclarkaec25102015-04-29 08:28:30 -0700175SkOpSegment::findNextOp simple
caryclark624637c2015-05-11 07:21:27 -0700176SkOpSegment::markDone id=-1 (5,2 1,3) t=0 [-1] (5,2) tEnd=0.351448746 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
177bridgeOp current id=-1 from=(3.5942049,2.35144877) to=(5,2)
caryclarkaec25102015-04-29 08:28:30 -0700178SkOpSegment::findNextOp simple
caryclark624637c2015-05-11 07:21:27 -0700179SkOpSegment::markDone id=-1 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 [-1] (4.48402119,2.56391668) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
180bridgeOp current id=-1 from=(5,2) to=(4.48402119,2.56391668)
181path.lineTo(5,2);
182path.cubicTo(4.84861231,2.15138769, 4.67430639,2.34861207, 4.48402119,2.56391668);
caryclarkaec25102015-04-29 08:28:30 -0700183SkOpSegment::findNextOp
caryclark624637c2015-05-11 07:21:27 -0700184SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=1/1 s=0.589250227 [-1] e=1 [-1] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
185SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=17/17 s=0.589250227 [-1] e=0.589197265 [-1] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done unorderable
186SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=17/17 s=0.999932596 [-1] e=1 [-1] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=1 done unorderable operand
187SkOpAngle::dumpOne [-1/-1] next=-1/-1 sect=1/1 s=0.999932596 [-1] e=0 [-1] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done operand
188SkOpSegment::activeOp id=-1 t=0.589250227 tEnd=0.589197265 op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
189SkOpSegment::activeOp id=-1 t=0.999932596 tEnd=1 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
190SkOpSegment::activeOp id=-1 t=0.999932596 tEnd=0 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
191SkOpSegment::markDone id=-1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 [-1] (3.00020218,3.99986529) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
192SkOpSegment::findNextOp from:[-1] to:[-1] start=7083932 end=7083244
193bridgeOp current id=-1 from=(4.48402119,2.56391668) to=(3.00020218,3.99986529)
194path.cubicTo(4.04589319,3.0596509, 3.52305317,3.65123534, 3.00020218,3.99986529);
195path.close();
196</div>
197
198<div id="cubics45u_debug">
199seg=1 {{{1, 3}, {1.84861219f, 5.54583645f}, {3.41736698f, 3.77081728f}, {4.48402119f, 2.56391668f}}}
200seg=2 {{{4.48402119f, 2.56391668f}, {4.67430639f, 2.34861207f}, {4.84861231f, 2.15138769f}, {5, 2}}}
201seg=3 {{{5, 2}, {1, 3}}}
202op union
203seg=4 {{{3, 4}, {2.61882615f, 4.38117361f}, {2.52823925f, 4.03588009f}, {2.7282393f, 3.51794004f}}}
204seg=5 {{{2.7282393f, 3.51794004f}, {3.05293441f, 2.67707705f}, {4.14352131f, 1.38117373f}, {6, 2}}}
205seg=6 {{{6, 2}, {3, 4}}}
206debugShowCubicIntersection wtTs[0]=1 {{{3,4}, {2.61882615,4.38117361}, {2.52823925,4.03588009}, {2.7282393,3.51794004}}} {{2.7282393,3.51794004}} wnTs[0]=0 {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}}
207debugShowCubicLineIntersection wtTs[0]=0 {{{3,4}, {2.61882615,4.38117361}, {2.52823925,4.03588009}, {2.7282393,3.51794004}}} {{3,4}} wnTs[0]=1 {{{6,2}, {3,4}}}
208debugShowCubicLineIntersection wtTs[0]=1 {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{6,2}} wnTs[0]=0 {{{6,2}, {3,4}}}
209debugShowCubicIntersection wtTs[0]=0 {{{3,4}, {2.61882615,4.38117361}, {2.52823925,4.03588009}, {2.7282393,3.51794004}}} {{3,4}} wtTs[1]=0.322114632 {{2.72210693,4.16072464}} wnTs[0]=0.589197 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} wnTs[1]=0.516302729
210SkOpSegment::addT insert t=0.589197265 segID=1 spanID=13
211SkOpSegment::addT insert t=0.322114632 segID=4 spanID=14
212SkOpSegment::addT insert t=0.516302729 segID=1 spanID=15
213debugShowCubicIntersection no intersect {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}}
214debugShowCubicIntersection no intersect {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}}
215debugShowCubicLineIntersection wtTs[0]=0.437504678 {{{2.7282393,3.51794004}, {3.05293441,2.67707705}, {4.14352131,1.38117373}, {6,2}}} {{3.5942049,2.35144877}} wnTs[0]=0.351449 {{{5,2}, {1,3}}}
216SkOpSegment::addT insert t=0.437504678 segID=5 spanID=16
217SkOpSegment::addT insert t=0.351448746 segID=3 spanID=17
218debugShowCubicLineIntersection wtTs[0]=0.589250227 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} {{3.00020218,3.99986529}} wnTs[0]=0.999933 {{{6,2}, {3,4}}}
219SkOpSegment::addT insert t=0.999932596 segID=6 spanID=18
220SkOpSegment::addT insert t=0.589250227 segID=1 spanID=19
221debugShowCubicLineIntersection no intersect {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}} {{{6,2}, {3,4}}}
222debugShowLineIntersection no intersect {{{6,2}, {3,4}}} {{{5,2}, {1,3}}}
223debugShowCubicIntersection wtTs[0]=1 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} {{4.48402119,2.56391668}} wnTs[0]=0 {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}}
224debugShowCubicLineIntersection wtTs[0]=0 {{{1,3}, {1.84861219,5.54583645}, {3.41736698,3.77081728}, {4.48402119,2.56391668}}} {{1,3}} wnTs[0]=1 {{{5,2}, {1,3}}}
225debugShowCubicLineIntersection wtTs[0]=1 {{{4.48402119,2.56391668}, {4.67430639,2.34861207}, {4.84861231,2.15138769}, {5,2}}} {{5,2}} wnTs[0]=0 {{{5,2}, {1,3}}}
226SkOpSegment::sortAngles [4] tStart=0 [7]
227SkOpAngle::after [4/1] 18/17 tStart=0 tEnd=0.322114632 < [1/12] 1/1 tStart=0.589197265 tEnd=0.589250227 < [1/11] 17/17 tStart=0.589197265 tEnd=0.516302729 T 5
228SkOpAngle::afterPart {{{3,4}, {2.87721833,4.1227816}, {2.78458726,4.17018661}, {2.72210693,4.16072464}}} id=4
229SkOpAngle::afterPart {{{3,4}, {3.00006742,3.99995506}, {3.00013476,3.99991025}, {3.00020218,3.99986529}}} id=1
230SkOpAngle::afterPart {{{3,4}, {2.9072112,4.06185918}, {2.81442231,4.11606536}, {2.72210693,4.16072464}}} id=1
231SkOpAngle::after [4/1] 18/17 tStart=0 tEnd=0.322114632 < [6/8] 1/1 tStart=1 tEnd=0.999932596 < [1/12] 1/1 tStart=0.589197265 tEnd=0.589250227 F 11
232SkOpAngle::afterPart {{{3,4}, {2.87721833,4.1227816}, {2.78458726,4.17018661}, {2.72210693,4.16072464}}} id=4
233SkOpAngle::afterPart {{{3,4}, {3.00020218,3.99986529}}} id=6
234SkOpAngle::afterPart {{{3,4}, {3.00006742,3.99995506}, {3.00013476,3.99991025}, {3.00020218,3.99986529}}} id=1
235SkOpAngle::after [1/12] 1/1 tStart=0.589197265 tEnd=0.589250227 < [6/8] 1/1 tStart=1 tEnd=0.999932596 < [1/11] 17/17 tStart=0.589197265 tEnd=0.516302729 T 12
236SkOpAngle::afterPart {{{3,4}, {3.00006742,3.99995506}, {3.00013476,3.99991025}, {3.00020218,3.99986529}}} id=1
237SkOpAngle::afterPart {{{3,4}, {3.00020218,3.99986529}}} id=6
238SkOpAngle::afterPart {{{3,4}, {2.9072112,4.06185918}, {2.81442231,4.11606536}, {2.72210693,4.16072464}}} id=1
239SkOpSegment::sortAngles [4] tStart=0.322114632 [14]
240SkOpAngle::after [4/2] 29/1 tStart=0.322114632 tEnd=0 < [1/9] 17/13 tStart=0.516302729 tEnd=0 < [4/3] 13/5 tStart=0.322114632 tEnd=1 F 11
241SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.78458726,4.17018661}, {2.87721833,4.1227816}, {3,4}}} id=4
242SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.06824885,4.47704065}, {1.43814079,4.31442231}, {1,3}}} id=1
243SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.59061803,4.14081206}, {2.59266219,3.86904402}, {2.7282393,3.51794004}}} id=4
244SkOpAngle::after [4/2] 29/1 tStart=0.322114632 tEnd=0 < [1/10] 1/1 tStart=0.516302729 tEnd=0.589197265 < [4/3] 13/5 tStart=0.322114632 tEnd=1 T 12
245SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.78458726,4.17018661}, {2.87721833,4.1227816}, {3,4}}} id=4
246SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.81442231,4.11606536}, {2.9072112,4.06185918}, {3,4}}} id=1
247SkOpAngle::afterPart {{{2.72210693,4.16072464}, {2.59061803,4.14081206}, {2.59266219,3.86904402}, {2.7282393,3.51794004}}} id=4
248SkOpSegment::sortAngles [5] tStart=0.437504678 [16]
249SkOpAngle::after [5/4] 17/21 tStart=0.437504678 tEnd=0 < [3/15] 1/1 tStart=0.351448746 tEnd=0 < [5/5] 1/1 tStart=0.437504678 tEnd=1 T 11
250SkOpAngle::afterPart {{{3.5942049,2.35144877}, {3.15895005,2.69507766}, {2.87029493,3.15005855}, {2.7282393,3.51794004}}} id=5
251SkOpAngle::afterPart {{{3.5942049,2.35144877}, {5,2}}} id=3
252SkOpAngle::afterPart {{{3.5942049,2.35144877}, {4.15380764,1.9096486}, {4.95573942,1.65191312}, {6,2}}} id=5
253SkOpAngle::after [5/4] 17/21 tStart=0.437504678 tEnd=0 < [3/16] 17/17 tStart=0.351448746 tEnd=1 < [3/15] 1/1 tStart=0.351448746 tEnd=0 F 12
254SkOpAngle::afterPart {{{3.5942049,2.35144877}, {3.15895005,2.69507766}, {2.87029493,3.15005855}, {2.7282393,3.51794004}}} id=5
255SkOpAngle::afterPart {{{3.5942049,2.35144877}, {1,3}}} id=3
256SkOpAngle::afterPart {{{3.5942049,2.35144877}, {5,2}}} id=3
257SkOpAngle::after [3/15] 1/1 tStart=0.351448746 tEnd=0 < [3/16] 17/17 tStart=0.351448746 tEnd=1 < [5/5] 1/1 tStart=0.437504678 tEnd=1 F 5
258SkOpAngle::afterPart {{{3.5942049,2.35144877}, {5,2}}} id=3
259SkOpAngle::afterPart {{{3.5942049,2.35144877}, {1,3}}} id=3
260SkOpAngle::afterPart {{{3.5942049,2.35144877}, {4.15380764,1.9096486}, {4.95573942,1.65191312}, {6,2}}} id=5
261SkOpAngle::after [5/5] 1/1 tStart=0.437504678 tEnd=1 < [3/16] 17/17 tStart=0.351448746 tEnd=1 < [5/4] 17/21 tStart=0.437504678 tEnd=0 T 11
262SkOpAngle::afterPart {{{3.5942049,2.35144877}, {4.15380764,1.9096486}, {4.95573942,1.65191312}, {6,2}}} id=5
263SkOpAngle::afterPart {{{3.5942049,2.35144877}, {1,3}}} id=3
264SkOpAngle::afterPart {{{3.5942049,2.35144877}, {3.15895005,2.69507766}, {2.87029493,3.15005855}, {2.7282393,3.51794004}}} id=5
265SkOpSegment::sortAngles [6] tStart=0.999932596 [18]
266SkOpAngle::after [6/6] 1/1 tStart=0.999932596 tEnd=0 < [1/13] 17/17 tStart=0.589250227 tEnd=0.589197265 < [6/7] 17/17 tStart=0.999932596 tEnd=1 T 11
267SkOpAngle::afterPart {{{3.00020218,3.99986529}, {6,2}}} id=6
268SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3.00013476,3.99991025}, {3.00006742,3.99995506}, {3,4}}} id=1
269SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3,4}}} id=6
270SkOpAngle::after [6/6] 1/1 tStart=0.999932596 tEnd=0 < [1/14] 1/1 tStart=0.589250227 tEnd=1 < [1/13] 17/17 tStart=0.589250227 tEnd=0.589197265 T 12
271SkOpAngle::afterPart {{{3.00020218,3.99986529}, {6,2}}} id=6
272SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3.52305312,3.65123542}, {4.04589321,3.05965083}, {4.48402119,2.56391668}}} id=1
273SkOpAngle::afterPart {{{3.00020218,3.99986529}, {3.00013476,3.99991025}, {3.00006742,3.99995506}, {3,4}}} id=1
274SkOpSegment::sortAngles [6] tStart=1 [12]
275SkOpSegment::sortAngles [1] tStart=0.516302729 [15]
276SkOpSegment::sortAngles [1] tStart=0.589197265 [13]
277SkOpSegment::sortAngles [1] tStart=0.589250227 [19]
278SkOpSegment::sortAngles [3] tStart=0.351448746 [17]
279SkOpSegment::debugShowActiveSpans id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 (3,4) tEnd=0.322114632 windSum=? windValue=1
280SkOpSegment::debugShowActiveSpans id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 (2.72210693,4.16072464) tEnd=1 windSum=? windValue=1
281SkOpSegment::debugShowActiveSpans id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 (2.7282393,3.51794004) tEnd=0.437504678 windSum=? windValue=1
282SkOpSegment::debugShowActiveSpans id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 (3.5942049,2.35144877) tEnd=1 windSum=? windValue=1
283SkOpSegment::debugShowActiveSpans id=6 (6,2 3,4) t=0 (6,2) tEnd=0.999932596 windSum=? windValue=1
284SkOpSegment::debugShowActiveSpans id=6 (6,2 3,4) t=0.999932596 (3.00020218,3.99986529) tEnd=1 windSum=? windValue=1
285SkOpSegment::debugShowActiveSpans id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 (1,3) tEnd=0.516302729 windSum=? windValue=1
286SkOpSegment::debugShowActiveSpans id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 (2.72210693,4.16072464) tEnd=0.589197265 windSum=? windValue=1
287SkOpSegment::debugShowActiveSpans id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589197265 (3,4) tEnd=0.589250227 windSum=? windValue=1
288SkOpSegment::debugShowActiveSpans id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 (3.00020218,3.99986529) tEnd=1 windSum=? windValue=1
289SkOpSegment::debugShowActiveSpans id=2 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 (4.48402119,2.56391668) tEnd=1 windSum=? windValue=1
290SkOpSegment::debugShowActiveSpans id=3 (5,2 1,3) t=0 (5,2) tEnd=0.351448746 windSum=? windValue=1
291SkOpSegment::debugShowActiveSpans id=3 (5,2 1,3) t=0.351448746 (3.5942049,2.35144877) tEnd=1 windSum=? windValue=1
292SkOpSpan::sortableTop dir=kTop seg=4 t=0.161057316 pt=(2.83844042,4.12995338)
293SkOpSpan::sortableTop [0] valid=1 operand=0 span=17 ccw=0 seg=3 {{{5, 2}, {1, 3}}} t=0.540389895 pt=(2.83844042,2.54039001) slope=(-4,1)
294SkOpSpan::sortableTop [1] valid=1 operand=1 span=9 ccw=1 seg=5 {{{2.7282393f, 3.51794004f}, {3.05293441f, 2.67707705f}, {4.14352131f, 1.38117373f}, {6, 2}}} t=0.0928134153 pt=(2.83844042,3.27394509) slope=(1.40059553,-2.71475011)
295SkOpSpan::sortableTop [2] valid=1 operand=0 span=15 ccw=1 seg=1 {{{1, 3}, {1.84861219f, 5.54583645f}, {3.41736698f, 3.77081728f}, {4.48402119f, 2.56391668f}}} t=0.546866125 pt=(2.83844042,4.09965467) slope=(3.81218461,-2.15374068)
296SkOpSpan::sortableTop [3] valid=1 operand=1 span=7 ccw=0 seg=4 {{{3, 4}, {2.61882615f, 4.38117361f}, {2.52823925f, 4.03588009f}, {2.7282393f, 3.51794004f}}} t=0.161057316 pt=(2.83844042,4.12995338) slope=(-0.862714624,0.484601174)
297SkOpSegment::markWinding id=3 (5,2 1,3) t=0.351448746 [17] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
298SkOpSegment::markWinding id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 [1] (1,3) tEnd=0.516302729 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
299SkOpSegment::markWinding id=3 (5,2 1,3) t=0.351448746 [17] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
300SkOpSegment::markWinding id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 [9] (2.7282393,3.51794004) tEnd=0.437504678 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
301SkOpSegment::markWinding id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 [9] (2.7282393,3.51794004) tEnd=0.437504678 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
302SkOpSegment::markWinding id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 [14] (2.72210693,4.16072464) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
303SkOpSegment::markWinding id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 [15] (2.72210693,4.16072464) tEnd=0.589197265 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
304SkOpSegment::markWinding id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 [15] (2.72210693,4.16072464) tEnd=0.589197265 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
305SkOpSegment::markWinding id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 [7] (3,4) tEnd=0.322114632 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
306SkOpSegment::markWinding id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 [7] (3,4) tEnd=0.322114632 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
307SkOpSegment::activeOp id=4 t=0.322114632 tEnd=0 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
308SkOpSegment::markWinding id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589197265 [13] (3,4) tEnd=0.589250227 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
309SkOpSegment::markAngle last segment=1 span=19 windSum=?
310SkOpSegment::markWinding id=6 (6,2 3,4) t=0.999932596 [18] (3.00020218,3.99986529) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
311SkOpSegment::markAngle last segment=6 span=18 windSum=-1
312SkOpSegment::findNextOp
313SkOpAngle::dumpOne [4/1] next=1/12 sect=18/17 s=0 [7] e=0.322114632 [14] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
314SkOpAngle::dumpOne [1/12] next=6/8 sect=1/1 s=0.589197265 [13] e=0.589250227 [19] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
315SkOpAngle::dumpOne [6/8] next=1/11 sect=1/1 s=1 [12] e=0.999932596 [18] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=1 operand
316SkOpAngle::dumpOne [1/11] next=4/1 sect=17/17 s=0.589197265 [13] e=0.516302729 [15] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-1
317SkOpSegment::activeOp id=1 t=0.589197265 tEnd=0.589250227 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
318SkOpSegment::findNextOp chase.append segment=1 span=19 windSum=-2147483647
319SkOpSegment::activeOp id=6 t=1 tEnd=0.999932596 op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
320SkOpSegment::markDone id=6 (6,2 3,4) t=0.999932596 [18] (3.00020218,3.99986529) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
321SkOpSegment::findNextOp chase.append segment=6 span=18 windSum=-1
322SkOpSegment::activeOp id=1 t=0.589197265 tEnd=0.516302729 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
323SkOpSegment::markDone id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.516302729 [15] (2.72210693,4.16072464) tEnd=0.589197265 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
324SkOpSegment::markDone id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0 [7] (3,4) tEnd=0.322114632 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
325SkOpSegment::findNextOp from:[4] to:[1] start=11952148 end=11952772
326bridgeOp current id=4 from=(2.72210693,4.16072464) to=(3,4)
327path.moveTo(2.72210693,4.16072464);
328path.cubicTo(2.78458714,4.17018652, 2.87721825,4.12278175, 3,4);
329SkOpSegment::markDone id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589197265 [13] (3,4) tEnd=0.589250227 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
330SkOpSegment::markWinding id=6 (6,2 3,4) t=0 [11] (6,2) tEnd=0.999932596 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
331SkOpSegment::markWinding id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 [16] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
332SkOpSegment::markAngle last segment=5 span=16 windSum=1
333SkOpSegment::markWinding id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 [19] (3.00020218,3.99986529) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
334SkOpSegment::markWinding id=2 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 [3] (4.48402119,2.56391668) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
335SkOpSegment::markWinding id=3 (5,2 1,3) t=0 [5] (5,2) tEnd=0.351448746 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
336SkOpSegment::markAngle last segment=3 span=17 windSum=1
337SkOpSegment::debugShowActiveSpans id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 (2.72210693,4.16072464) tEnd=1 windSum=-1 oppSum=1 windValue=1 oppValue=0
338SkOpSegment::debugShowActiveSpans id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 (2.7282393,3.51794004) tEnd=0.437504678 windSum=-1 oppSum=1 windValue=1 oppValue=0
339SkOpSegment::debugShowActiveSpans id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 (3.5942049,2.35144877) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
340SkOpSegment::debugShowActiveSpans id=6 (6,2 3,4) t=0 (6,2) tEnd=0.999932596 windSum=1 oppSum=0 windValue=1 oppValue=0
341SkOpSegment::debugShowActiveSpans id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 (1,3) tEnd=0.516302729 windSum=1 oppSum=0 windValue=1 oppValue=0
342SkOpSegment::debugShowActiveSpans id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 (3.00020218,3.99986529) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
343SkOpSegment::debugShowActiveSpans id=2 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 (4.48402119,2.56391668) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
344SkOpSegment::debugShowActiveSpans id=3 (5,2 1,3) t=0 (5,2) tEnd=0.351448746 windSum=1 oppSum=0 windValue=1 oppValue=0
345SkOpSegment::debugShowActiveSpans id=3 (5,2 1,3) t=0.351448746 (3.5942049,2.35144877) tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
346SkOpSegment::activeOp id=6 t=0.999932596 tEnd=0 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
347SkOpSegment::findNextOp simple
348SkOpSegment::markDone id=6 (6,2 3,4) t=0 [11] (6,2) tEnd=0.999932596 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
349bridgeOp current id=6 from=(3.00020218,3.99986529) to=(6,2)
350SkOpSegment::findNextOp
351SkOpAngle::dumpOne [5/5] next=3/16 sect=1/1 s=0.437504678 [16] e=1 [10] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 operand
352SkOpAngle::dumpOne [3/16] next=5/4 sect=17/17 s=0.351448746 [17] e=1 [6] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
353SkOpAngle::dumpOne [5/4] next=3/15 sect=17/21 s=0.437504678 [16] e=0 [9] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=1 operand
354SkOpAngle::dumpOne [3/15] next=5/5 sect=1/1 s=0.351448746 [17] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0
355SkOpSegment::activeOp id=3 t=0.351448746 tEnd=1 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
356SkOpSegment::markDone id=3 (5,2 1,3) t=0.351448746 [17] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
357SkOpSegment::markDone id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0 [1] (1,3) tEnd=0.516302729 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
358SkOpSegment::activeOp id=5 t=0.437504678 tEnd=0 op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
359SkOpSegment::markDone id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0 [9] (2.7282393,3.51794004) tEnd=0.437504678 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
360SkOpSegment::markDone id=4 (3,4 2.61882615,4.38117361 2.52823925,4.03588009 2.7282393,3.51794004) t=0.322114632 [14] (2.72210693,4.16072464) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0
361SkOpSegment::activeOp id=3 t=0.351448746 tEnd=0 op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
362SkOpSegment::markDone id=5 (2.7282393,3.51794004 3.05293441,2.67707705 4.14352131,1.38117373 6,2) t=0.437504678 [16] (3.5942049,2.35144877) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
363SkOpSegment::findNextOp from:[5] to:[3] start=11952564 end=11951100
364bridgeOp current id=5 from=(6,2) to=(3.5942049,2.35144877)
365path.moveTo(3.00020218,3.99986529);
366path.lineTo(6,2);
367path.cubicTo(4.9557395,1.65191317, 4.15380764,1.90964866, 3.5942049,2.35144877);
368SkOpSegment::findNextOp simple
369SkOpSegment::markDone id=3 (5,2 1,3) t=0 [5] (5,2) tEnd=0.351448746 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
370bridgeOp current id=3 from=(3.5942049,2.35144877) to=(5,2)
371SkOpSegment::findNextOp simple
372SkOpSegment::markDone id=2 (4.48402119,2.56391668 4.67430639,2.34861207 4.84861231,2.15138769 5,2) t=0 [3] (4.48402119,2.56391668) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
373bridgeOp current id=2 from=(5,2) to=(4.48402119,2.56391668)
374path.lineTo(5,2);
375path.cubicTo(4.84861231,2.15138769, 4.67430639,2.34861207, 4.48402119,2.56391668);
376SkOpSegment::findNextOp
377SkOpAngle::dumpOne [1/14] next=1/13 sect=1/1 s=0.589250227 [19] e=1 [2] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
378SkOpAngle::dumpOne [1/13] next=6/7 sect=17/17 s=0.589250227 [19] e=0.589197265 [13] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done unorderable
379SkOpAngle::dumpOne [6/7] next=6/6 sect=17/17 s=0.999932596 [18] e=1 [12] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=1 done unorderable operand
380SkOpAngle::dumpOne [6/6] next=1/14 sect=1/1 s=0.999932596 [18] e=0 [11] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done operand
381SkOpSegment::activeOp id=1 t=0.589250227 tEnd=0.589197265 op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
382SkOpSegment::activeOp id=6 t=0.999932596 tEnd=1 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
383SkOpSegment::activeOp id=6 t=0.999932596 tEnd=0 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
384SkOpSegment::markDone id=1 (1,3 1.84861219,5.54583645 3.41736698,3.77081728 4.48402119,2.56391668) t=0.589250227 [19] (3.00020218,3.99986529) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
385SkOpSegment::findNextOp from:[1] to:[6] start=11952668 end=11951916
386bridgeOp current id=1 from=(4.48402119,2.56391668) to=(3.00020218,3.99986529)
387path.cubicTo(4.04589319,3.0596509, 3.52305317,3.65123534, 3.00020218,3.99986529);
caryclark03b03ca2015-04-23 09:13:37 -0700388path.close();
caryclarkdac1d172014-06-17 05:15:38 -0700389</div>
caryclark54359292015-03-26 07:52:43 -0700390
caryclarkdac1d172014-06-17 05:15:38 -0700391</div>
392
393<script type="text/javascript">
394
395var testDivs = [
caryclark624637c2015-05-11 07:21:27 -0700396 cubics45u_release,
397 cubics45u_debug,
caryclarkdac1d172014-06-17 05:15:38 -0700398];
399
400var decimal_places = 3; // make this 3 to show more precision
401
402var tests = [];
403var testLines = [];
404var testTitles = [];
405var testIndex = 0;
406var ctx;
407
408var xmin, xmax, focusXmin, focusXmax;
409var ymin, ymax, focusYmin, focusYmax;
410var scale;
411var mouseX, mouseY;
412var srcLeft, srcTop;
413var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700414var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700415var curveT = 0;
416
417var pt_labels = 2;
418var collect_bounds = false;
419var control_lines = 0;
420var curve_t = false;
421var debug_xy = 1;
422var focus_enabled = false;
423var focus_on_selection = false;
424var step_limit = 0;
425var draw_active = false;
426var draw_add = false;
427var draw_angle = 0;
caryclark624637c2015-05-11 07:21:27 -0700428var draw_coincidence = false;
caryclarkdac1d172014-06-17 05:15:38 -0700429var draw_deriviatives = 0;
430var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700431var draw_id = false;
432var draw_intersection = 0;
433var draw_intersectT = false;
434var draw_legend = true;
435var draw_log = false;
436var draw_mark = false;
437var draw_midpoint = false;
438var draw_op = 0;
439var draw_sequence = false;
440var draw_sort = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700441var draw_top = false;
caryclarkdac1d172014-06-17 05:15:38 -0700442var draw_path = 3;
443var draw_computed = 0;
444var retina_scale = !!window.devicePixelRatio;
445
446var activeCount = 0;
447var addCount = 0;
448var angleCount = 0;
caryclark624637c2015-05-11 07:21:27 -0700449var coinCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700450var opCount = 0;
451var sectCount = 0;
452var sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700453var topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700454var markCount = 0;
455var activeMax = 0;
456var addMax = 0;
457var angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -0700458var coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700459var sectMax = 0;
460var sectMax2 = 0;
461var sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700462var topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700463var markMax = 0;
464var opMax = 0;
465var stepMax = 0;
466var lastIndex = 0;
467var hasPath = false;
468var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700469var angleBetween = false;
470var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700471
472var firstActiveSpan = -1;
473var logStart = -1;
474var logRange = 0;
475
476var SPAN_ID = 0;
477var SPAN_X1 = SPAN_ID + 1;
478var SPAN_Y1 = SPAN_X1 + 1;
479var SPAN_X2 = SPAN_Y1 + 1;
480var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700481
caryclarkdac1d172014-06-17 05:15:38 -0700482var SPAN_L_T = SPAN_Y2 + 1;
483var SPAN_L_TX = SPAN_L_T + 1;
484var SPAN_L_TY = SPAN_L_TX + 1;
485var SPAN_L_TEND = SPAN_L_TY + 1;
486var SPAN_L_OTHER = SPAN_L_TEND + 1;
487var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
488var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
489var SPAN_L_SUM = SPAN_L_OTHERI + 1;
490var SPAN_L_VAL = SPAN_L_SUM + 1;
491var SPAN_L_OPP = SPAN_L_VAL + 1;
492
493var SPAN_X3 = SPAN_Y2 + 1;
494var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700495
caryclarkdac1d172014-06-17 05:15:38 -0700496var SPAN_Q_T = SPAN_Y3 + 1;
497var SPAN_Q_TX = SPAN_Q_T + 1;
498var SPAN_Q_TY = SPAN_Q_TX + 1;
499var SPAN_Q_TEND = SPAN_Q_TY + 1;
500var SPAN_Q_OTHER = SPAN_Q_TEND + 1;
501var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
502var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
503var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
504var SPAN_Q_VAL = SPAN_Q_SUM + 1;
505var SPAN_Q_OPP = SPAN_Q_VAL + 1;
506
caryclark1049f122015-04-20 08:31:59 -0700507var SPAN_K_W = SPAN_Y3 + 1;
508var SPAN_K_T = SPAN_K_W + 1;
509var SPAN_K_TX = SPAN_K_T + 1;
510var SPAN_K_TY = SPAN_K_TX + 1;
511var SPAN_K_TEND = SPAN_K_TY + 1;
512var SPAN_K_OTHER = SPAN_K_TEND + 1;
513var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
514var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
515var SPAN_K_SUM = SPAN_K_OTHERI + 1;
516var SPAN_K_VAL = SPAN_K_SUM + 1;
517var SPAN_K_OPP = SPAN_K_VAL + 1;
518
caryclarkdac1d172014-06-17 05:15:38 -0700519var SPAN_X4 = SPAN_Y3 + 1;
520var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700521
caryclarkdac1d172014-06-17 05:15:38 -0700522var SPAN_C_T = SPAN_Y4 + 1;
523var SPAN_C_TX = SPAN_C_T + 1;
524var SPAN_C_TY = SPAN_C_TX + 1;
525var SPAN_C_TEND = SPAN_C_TY + 1;
526var SPAN_C_OTHER = SPAN_C_TEND + 1;
527var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
528var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
529var SPAN_C_SUM = SPAN_C_OTHERI + 1;
530var SPAN_C_VAL = SPAN_C_SUM + 1;
531var SPAN_C_OPP = SPAN_C_VAL + 1;
532
533var ACTIVE_LINE_SPAN = 1;
534var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700535var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
536var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700537
538var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
539var ADD_LINETO = ADD_MOVETO + 1;
540var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700541var ADD_CONICTO = ADD_QUADTO + 1;
542var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700543var ADD_CLOSE = ADD_CUBICTO + 1;
544var ADD_FILL = ADD_CLOSE + 1;
545
546var PATH_LINE = ADD_FILL + 1;
547var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700548var PATH_CONIC = PATH_QUAD + 1;
549var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700550
551var INTERSECT_LINE = PATH_CUBIC + 1;
552var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
553var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
554var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
555var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
556var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
557var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
558var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
559var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700560var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
561var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
562var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
563var INTERSECT_CONIC = INTERSECT_CONIC_LINE_NO + 1;
564var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
565var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
566var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700567var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
568var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
569var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
570var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
571var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
572var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
573var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
574var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
575var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
576var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
577var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
578var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
579var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
580var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
581// FIXME: add cubic 5- 9
582var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
583
584var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
585var SORT_BINARY = SORT_UNARY + 1;
586
587var OP_DIFFERENCE = SORT_BINARY + 1;
588var OP_INTERSECT = OP_DIFFERENCE + 1;
589var OP_UNION = OP_INTERSECT + 1;
590var OP_XOR = OP_UNION + 1;
591
592var MARK_LINE = OP_XOR + 1;
593var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700594var MARK_CONIC = MARK_QUAD + 1;
595var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700596var MARK_DONE_LINE = MARK_CUBIC + 1;
597var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700598var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
599var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700600var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
601var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700602var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
603var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700604var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
605var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700606var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
607var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700608var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
609var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700610var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
611var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700612var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
613var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700614var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
615var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700616var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
617
618var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
619var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
620
caryclark624637c2015-05-11 07:21:27 -0700621var ANGLE_AFTER = COMPUTED_SET_2 + 1;
caryclark54359292015-03-26 07:52:43 -0700622var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700623
caryclark54359292015-03-26 07:52:43 -0700624var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700625
caryclark624637c2015-05-11 07:21:27 -0700626var COIN_MAIN_SPAN = ACTIVE_OP + 1;
627var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1;
628
629var FRAG_TYPE_LAST = COIN_OPP_SPAN;
caryclarkdac1d172014-06-17 05:15:38 -0700630
631var REC_TYPE_UNKNOWN = -1;
632var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700633var REC_TYPE_PATH2 = 1;
634var REC_TYPE_SECT = 2;
635var REC_TYPE_ACTIVE = 3;
636var REC_TYPE_ADD = 4;
637var REC_TYPE_SORT = 5;
638var REC_TYPE_OP = 6;
639var REC_TYPE_MARK = 7;
640var REC_TYPE_COMPUTED = 8;
641var REC_TYPE_COIN = 9;
642var REC_TYPE_ANGLE = 10;
643var REC_TYPE_ACTIVE_OP = 11;
644var REC_TYPE_AFTERPART = 12;
caryclark03b03ca2015-04-23 09:13:37 -0700645var REC_TYPE_TOP = 13;
caryclark624637c2015-05-11 07:21:27 -0700646var REC_TYPE_COINCIDENCE = 14;
647var REC_TYPE_LAST = REC_TYPE_COINCIDENCE;
caryclarkdac1d172014-06-17 05:15:38 -0700648
649function strs_to_nums(strs) {
650 var result = [];
651 for (var idx = 1; idx < strs.length; ++idx) {
652 var str = strs[idx];
653 var num = parseFloat(str);
654 if (isNaN(num)) {
655 result.push(str);
656 } else {
657 result.push(num);
658 }
659 }
660 return result;
661}
662
663function filter_str_by(id, str, regex, array) {
664 if (regex.test(str)) {
665 var strs = regex.exec(str);
666 var result = strs_to_nums(strs);
667 array.push(id);
668 array.push(result);
669 return true;
670 }
671 return false;
672}
673
674function construct_regexp2(pattern) {
675 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
676 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
677 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700678 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700679 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
680 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
681 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700682 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700683 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
684 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
685 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700686 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700687 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700688 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700689 escape = escape.replace(/NUM/g, "(-?\\d+)");
690 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
691 return new RegExp(escape, 'i');
692}
693
694function construct_regexp2c(pattern) {
695 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
696 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700697 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700698 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700699 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
700 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700701 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700702 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700703 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
caryclark54359292015-03-26 07:52:43 -0700704 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 -0700705 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700706 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700707 escape = escape.replace(/OPER/g, "[a-z]+");
708 escape = escape.replace(/PATH/g, "pathB?");
709 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700710 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700711 escape = escape.replace(/NUM/g, "(-?\\d+)");
712 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
713 return new RegExp(escape, 'i');
714}
715
716function match_regexp(str, lineNo, array, id, pattern) {
717 var regex = construct_regexp2(pattern);
718 if (filter_str_by(id, str, regex, array)) {
719 return true;
720 }
721 regex = construct_regexp2c(pattern);
722 return filter_str_by(id, str, regex, array);
723}
724
725function endsWith(str, suffix) {
726 return str.indexOf(suffix, str.length - suffix.length) !== -1;
727}
728
729function parse_all(test) {
730 var lines = test.match(/[^\r\n]+/g);
731 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
732 var record = [];
733 var recType = REC_TYPE_UNKNOWN;
734 var lastLineNo;
735 var moveX, moveY;
736 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
737 var line = lines[lineNo];
738 if (line.length == 0) {
739 continue;
740 }
741 var opStart = "SkOpSegment::";
742 if (line.lastIndexOf(opStart, 0) === 0) {
743 line = line.substr(opStart.length);
744 }
745 var angleStart = "SkOpAngle::";
746 if (line.lastIndexOf(angleStart, 0) === 0) {
747 line = line.substr(angleStart.length);
748 }
caryclark624637c2015-05-11 07:21:27 -0700749 var coinStart = "SkOpCoincidence::";
750 if (line.lastIndexOf(coinStart, 0) === 0) {
751 line = line.substr(coinStart.length);
752 }
caryclark54359292015-03-26 07:52:43 -0700753 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
caryclark624637c2015-05-11 07:21:27 -0700754 : line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE
caryclark54359292015-03-26 07:52:43 -0700755 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclarkdac1d172014-06-17 05:15:38 -0700756 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
caryclark54359292015-03-26 07:52:43 -0700757 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700758 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
759 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
760 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
761 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
762 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
caryclark03b03ca2015-04-23 09:13:37 -0700763 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
caryclarkdac1d172014-06-17 05:15:38 -0700764 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
765 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
766 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
767 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
768 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700769 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700770 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
771 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
772 : REC_TYPE_UNKNOWN;
773 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
774 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
775 if (recType != REC_TYPE_UNKNOWN) {
776 records.push(recType);
777 records.push(lastLineNo);
778 records.push(record);
779 }
780 record = [];
781 recType = type;
782 lastLineNo = lineNo;
783 }
784 var found = false;
785 switch (recType) {
786 case REC_TYPE_ACTIVE:
787 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700788" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700789 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700790" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700791 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700792" id=IDX CONIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700793 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark624637c2015-05-11 07:21:27 -0700794" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
795 ) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
796" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
797 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
798" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
799 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
800" id=IDX CONIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
801 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
802" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700803 );
804 break;
805 case REC_TYPE_ACTIVE_OP:
806 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
807" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
808 );
809 break;
810 case REC_TYPE_ADD:
811 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
812 moveX = record[1][0];
813 moveY = record[1][1];
814 found = true;
815 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
816 record[1].unshift(moveY);
817 record[1].unshift(moveX);
818 moveX = record[1][2];
819 moveY = record[1][3];
820 found = true;
821 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
822 record[1].unshift(moveY);
823 record[1].unshift(moveX);
824 moveX = record[1][4];
825 moveY = record[1][5];
826 found = true;
caryclark1049f122015-04-20 08:31:59 -0700827 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
828 record[1].unshift(moveY);
829 record[1].unshift(moveX);
830 moveX = record[1][4];
831 moveY = record[1][5];
832 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700833 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
834 record[1].unshift(moveY);
835 record[1].unshift(moveX);
836 moveX = record[1][6];
837 moveY = record[1][7];
838 found = true;
839 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
840 found = true;
841 } else {
842 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
843 }
844 break;
caryclark54359292015-03-26 07:52:43 -0700845 case REC_TYPE_AFTERPART:
846 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL")
847 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL")
caryclark1049f122015-04-20 08:31:59 -0700848 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL")
caryclark54359292015-03-26 07:52:43 -0700849 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL")
850 break;
caryclarkdac1d172014-06-17 05:15:38 -0700851 case REC_TYPE_ANGLE:
852 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
caryclarkdac1d172014-06-17 05:15:38 -0700853"[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");
854 break;
855 case REC_TYPE_COIN:
856 found = true;
857 break;
caryclark624637c2015-05-11 07:21:27 -0700858 case REC_TYPE_COINCIDENCE:
859 found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" +
860" + id=IDX t=T_VAL tEnd=T_VAL"
861 ) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" +
862" - id=IDX t=T_VAL tEnd=T_VAL"
863 );
864 break;
caryclarkdac1d172014-06-17 05:15:38 -0700865 case REC_TYPE_COMPUTED:
866 found = line == "computed quadratics given"
867 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
868 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
869 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -0700870 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -0700871 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
872 );
873 break;
874 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700875 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
876 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700877 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -0700878 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
879 );
880 break;
881 case REC_TYPE_PATH2:
882 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
883 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -0700884 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -0700885 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -0700886 );
887 break;
888 case REC_TYPE_SECT:
889 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
890" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
891 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
892" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
893 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
894" no intersect LINE_VAL LINE_VAL"
895 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
896" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
897 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
898" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
899 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
900" no intersect QUAD_VAL LINE_VAL"
901 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
902" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
903 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
904" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
905 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
906" no intersect QUAD_VAL QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700907 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
908" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
909 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
910" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
911 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
912" no intersect CONIC_VAL LINE_VAL"
913 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
914" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
915 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
916" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
917 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
918" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -0700919 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
920" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
921 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
922" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
923 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
924" 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"
925 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
926" no intersect CUBIC_VAL LINE_VAL"
927 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
928" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
929 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
930" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
931 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
932" 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"
933 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
934" 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"
935 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
936" no intersect CUBIC_VAL QUAD_VAL"
937 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
938" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
939 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
940" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
941 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
942" 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"
943 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
944" 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"
945 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
946" no intersect CUBIC_VAL CUBIC_VAL"
947 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
948" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
949 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
950" no self intersect CUBIC_VAL"
951 );
952 break;
953 case REC_TYPE_SORT:
954 var hasDone = / done/.test(line);
955 var hasUnorderable = / unorderable/.test(line);
956 var hasSmall = / small/.test(line);
957 var hasTiny = / tiny/.test(line);
958 var hasOperand = / operand/.test(line);
959 var hasStop = / stop/.test(line);
960 line.replace(/[ a-z]+$/, "");
961 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
962" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
963 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
964" [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"
965 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
966" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
967 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
968" [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"
969 );
970 if (found) {
971 record[1].push(hasDone);
972 record[1].push(hasUnorderable);
973 record[1].push(hasSmall);
974 record[1].push(hasTiny);
975 record[1].push(hasOperand);
976 record[1].push(hasStop);
977 }
978 break;
caryclark03b03ca2015-04-23 09:13:37 -0700979 case REC_TYPE_TOP:
980 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
981" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
982 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
983" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
984 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
985" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
986 );
987 break;
caryclarkdac1d172014-06-17 05:15:38 -0700988 case REC_TYPE_MARK:
989 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700990" 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 -0700991 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700992" 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 -0700993 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
994" 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 -0700995 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700996" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
997 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
998" 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"
999 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
1000" 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 -07001001 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
1002" 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 -07001003 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
1004" 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 -07001005 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
1006" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
1007 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
1008" 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 -07001009 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
1010" 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 -07001011 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
1012" 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 -07001013 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -07001014" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -07001015 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1016" last segment=IDX span=IDX windSum=OPT");
caryclarkdac1d172014-06-17 05:15:38 -07001017 break;
1018 case REC_TYPE_OP:
1019 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
1020 || line.lastIndexOf("operator<", 0) === 0) {
1021 found = true;
1022 break;
1023 }
caryclark54359292015-03-26 07:52:43 -07001024 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -07001025 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -07001026 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -07001027 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
1028 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
1029 );
1030 break;
1031 case REC_TYPE_UNKNOWN:
1032 found = true;
1033 break;
1034 }
1035 if (!found) {
1036 console.log(line + " [" + lineNo + "] of type " + type + " not found");
1037 }
1038 }
1039 if (recType != REC_TYPE_UNKNOWN) {
1040 records.push(recType);
1041 records.push(lastLineNo);
1042 records.push(record);
1043 }
1044 if (records.length >= 1) {
1045 tests[testIndex] = records;
1046 testLines[testIndex] = lines;
1047 }
1048}
1049
1050function init(test) {
1051 var canvas = document.getElementById('canvas');
1052 if (!canvas.getContext) return;
1053 ctx = canvas.getContext('2d');
1054 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
1055 var unscaledWidth = window.innerWidth - 20;
1056 var unscaledHeight = window.innerHeight - 20;
1057 screenWidth = unscaledWidth;
1058 screenHeight = unscaledHeight;
1059 canvas.width = unscaledWidth * resScale;
1060 canvas.height = unscaledHeight * resScale;
1061 canvas.style.width = unscaledWidth + 'px';
1062 canvas.style.height = unscaledHeight + 'px';
1063 if (resScale != 1) {
1064 ctx.scale(resScale, resScale);
1065 }
1066 xmin = Infinity;
1067 xmax = -Infinity;
1068 ymin = Infinity;
1069 ymax = -Infinity;
1070 hasPath = hasComputedPath = false;
1071 firstActiveSpan = -1;
1072 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1073 var recType = test[tIndex];
1074 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
1075 console.log("unknown rec type: " + recType);
1076 throw "stop execution";
1077 }
1078 var records = test[tIndex + 2];
1079 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1080 var fragType = records[recordIndex];
1081 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
1082 console.log("unknown in range frag type: " + fragType);
1083 throw "stop execution";
1084 }
1085 var frags = records[recordIndex + 1];
1086 var first = 0;
1087 var last = -1;
1088 var first2 = 0;
1089 var last2 = 0;
1090 switch (recType) {
1091 case REC_TYPE_COMPUTED:
1092 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
1093 break;
1094 }
1095 hasComputedPath = true;
1096 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001097 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -07001098 switch (fragType) {
1099 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07001100 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -07001101 break;
caryclark1049f122015-04-20 08:31:59 -07001102 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07001103 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07001104 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -07001105 break;
1106 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07001107 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -07001108 break;
1109 default:
1110 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
1111 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1112 throw "stop execution";
1113 }
1114 if (recType == REC_TYPE_PATH) {
1115 hasPath = true;
1116 }
1117 break;
caryclark54359292015-03-26 07:52:43 -07001118 case REC_TYPE_PATH2:
1119 first = 1;
1120 switch (fragType) {
1121 case PATH_LINE:
1122 last = 5;
1123 break;
caryclark1049f122015-04-20 08:31:59 -07001124 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001125 case PATH_QUAD:
1126 last = 7;
1127 break;
1128 case PATH_CUBIC:
1129 last = 9;
1130 break;
1131 default:
1132 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
1133 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1134 throw "stop execution";
1135 }
1136 if (recType == REC_TYPE_PATH2) {
1137 hasPath = true;
1138 }
1139 break;
caryclarkdac1d172014-06-17 05:15:38 -07001140 case REC_TYPE_ACTIVE:
1141 if (firstActiveSpan < 0) {
1142 firstActiveSpan = tIndex;
1143 }
1144 first = 1;
1145 switch (fragType) {
1146 case ACTIVE_LINE_SPAN:
1147 last = 5;
1148 break;
caryclark1049f122015-04-20 08:31:59 -07001149 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -07001150 case ACTIVE_QUAD_SPAN:
1151 last = 7;
1152 break;
1153 case ACTIVE_CUBIC_SPAN:
1154 last = 9;
1155 break;
1156 default:
1157 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1158 throw "stop execution";
1159 }
1160 break;
1161 case REC_TYPE_ADD:
1162 switch (fragType) {
1163 case ADD_MOVETO:
1164 break;
1165 case ADD_LINETO:
1166 last = 4;
1167 break;
caryclark1049f122015-04-20 08:31:59 -07001168 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -07001169 case ADD_QUADTO:
1170 last = 6;
1171 break;
1172 case ADD_CUBICTO:
1173 last = 8;
1174 break;
1175 case ADD_CLOSE:
1176 case ADD_FILL:
1177 break;
1178 default:
1179 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1180 throw "stop execution";
1181 }
1182 break;
caryclark54359292015-03-26 07:52:43 -07001183 case REC_TYPE_AFTERPART:
1184 switch (fragType) {
1185 case PATH_LINE:
1186 last = 4;
1187 break;
caryclark1049f122015-04-20 08:31:59 -07001188 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001189 case PATH_QUAD:
1190 last = 6;
1191 break;
1192 case PATH_CUBIC:
1193 last = 8;
1194 break;
1195 default:
1196 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1197 throw "stop execution";
1198 }
1199 break;
caryclarkdac1d172014-06-17 05:15:38 -07001200 case REC_TYPE_SECT:
1201 switch (fragType) {
1202 case INTERSECT_LINE:
1203 first = 1; last = 5; first2 = 8; last2 = 12;
1204 break;
1205 case INTERSECT_LINE_2:
1206 first = 1; last = 5; first2 = 11; last2 = 15;
1207 break;
1208 case INTERSECT_LINE_NO:
1209 first = 0; last = 4; first2 = 4; last2 = 8;
1210 break;
caryclark1049f122015-04-20 08:31:59 -07001211 case INTERSECT_CONIC_LINE:
1212 first = 1; last = 7; first2 = 11; last2 = 15;
1213 break;
caryclarkdac1d172014-06-17 05:15:38 -07001214 case INTERSECT_QUAD_LINE:
1215 first = 1; last = 7; first2 = 10; last2 = 14;
1216 break;
caryclark1049f122015-04-20 08:31:59 -07001217 case INTERSECT_CONIC_LINE_2:
1218 first = 1; last = 7; first2 = 14; last2 = 18;
1219 break;
caryclarkdac1d172014-06-17 05:15:38 -07001220 case INTERSECT_QUAD_LINE_2:
1221 first = 1; last = 7; first2 = 13; last2 = 17;
1222 break;
caryclark1049f122015-04-20 08:31:59 -07001223 case INTERSECT_CONIC_LINE_NO:
1224 first = 0; last = 6; first2 = 7; last2 = 11;
1225 break;
caryclarkdac1d172014-06-17 05:15:38 -07001226 case INTERSECT_QUAD_LINE_NO:
1227 first = 0; last = 6; first2 = 6; last2 = 10;
1228 break;
caryclark1049f122015-04-20 08:31:59 -07001229 case INTERSECT_CONIC:
1230 first = 1; last = 7; first2 = 11; last2 = 17;
1231 break;
caryclarkdac1d172014-06-17 05:15:38 -07001232 case INTERSECT_QUAD:
1233 first = 1; last = 7; first2 = 10; last2 = 16;
1234 break;
caryclark1049f122015-04-20 08:31:59 -07001235 case INTERSECT_CONIC_2:
1236 first = 1; last = 7; first2 = 14; last2 = 20;
1237 break;
caryclarkdac1d172014-06-17 05:15:38 -07001238 case INTERSECT_QUAD_2:
1239 first = 1; last = 7; first2 = 13; last2 = 19;
1240 break;
caryclark1049f122015-04-20 08:31:59 -07001241 case INTERSECT_CONIC_NO:
1242 first = 0; last = 6; first2 = 7; last2 = 13;
1243 break;
caryclarkdac1d172014-06-17 05:15:38 -07001244 case INTERSECT_QUAD_NO:
1245 first = 0; last = 6; first2 = 6; last2 = 12;
1246 break;
1247 case INTERSECT_SELF_CUBIC:
1248 first = 1; last = 9;
1249 break;
1250 case INTERSECT_SELF_CUBIC_NO:
1251 first = 0; last = 8;
1252 break;
1253 case INTERSECT_CUBIC_LINE:
1254 first = 1; last = 9; first2 = 12; last2 = 16;
1255 break;
1256 case INTERSECT_CUBIC_LINE_2:
1257 first = 1; last = 9; first2 = 15; last2 = 19;
1258 break;
1259 case INTERSECT_CUBIC_LINE_3:
1260 first = 1; last = 9; first2 = 18; last2 = 22;
1261 break;
1262 case INTERSECT_CUBIC_LINE_NO:
1263 first = 0; last = 8; first2 = 8; last2 = 12;
1264 break;
1265 case INTERSECT_CUBIC_QUAD:
1266 first = 1; last = 9; first2 = 12; last2 = 18;
1267 break;
1268 case INTERSECT_CUBIC_QUAD_2:
1269 first = 1; last = 9; first2 = 15; last2 = 21;
1270 break;
1271 case INTERSECT_CUBIC_QUAD_3:
1272 first = 1; last = 9; first2 = 18; last2 = 24;
1273 break;
1274 case INTERSECT_CUBIC_QUAD_4:
1275 first = 1; last = 9; first2 = 21; last2 = 27;
1276 break;
1277 case INTERSECT_CUBIC_QUAD_NO:
1278 first = 0; last = 8; first2 = 8; last2 = 14;
1279 break;
1280 case INTERSECT_CUBIC:
1281 first = 1; last = 9; first2 = 12; last2 = 20;
1282 break;
1283 case INTERSECT_CUBIC_2:
1284 first = 1; last = 9; first2 = 15; last2 = 23;
1285 break;
1286 case INTERSECT_CUBIC_3:
1287 first = 1; last = 9; first2 = 18; last2 = 26;
1288 break;
1289 case INTERSECT_CUBIC_4:
1290 first = 1; last = 9; first2 = 21; last2 = 29;
1291 break;
1292 case INTERSECT_CUBIC_NO:
1293 first = 0; last = 8; first2 = 8; last2 = 16;
1294 break;
1295 default:
1296 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1297 throw "stop execution";
1298 }
1299 break;
1300 default:
1301 continue;
1302 }
1303 for (var idx = first; idx < last; idx += 2) {
1304 xmin = Math.min(xmin, frags[idx]);
1305 xmax = Math.max(xmax, frags[idx]);
1306 ymin = Math.min(ymin, frags[idx + 1]);
1307 ymax = Math.max(ymax, frags[idx + 1]);
1308 }
1309 for (var idx = first2; idx < last2; idx += 2) {
1310 xmin = Math.min(xmin, frags[idx]);
1311 xmax = Math.max(xmax, frags[idx]);
1312 ymin = Math.min(ymin, frags[idx + 1]);
1313 ymax = Math.max(ymax, frags[idx + 1]);
1314 }
1315 }
1316 }
1317 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1318 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1319 var recType = test[tIndex];
1320 var records = test[tIndex + 2];
1321 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1322 var fragType = records[recordIndex];
1323 var frags = records[recordIndex + 1];
1324 switch (recType) {
1325 case REC_TYPE_ACTIVE_OP:
1326 if (!draw_op) {
1327 break;
1328 }
1329 {
1330 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1331 curve_extremes(curve, angleBounds);
1332 }
1333 break;
1334 case REC_TYPE_ANGLE:
1335 if (!draw_angle) {
1336 break;
1337 }
caryclark54359292015-03-26 07:52:43 -07001338 {
caryclarkdac1d172014-06-17 05:15:38 -07001339 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1340 curve_extremes(curve, angleBounds);
1341 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1342 curve_extremes(curve, angleBounds);
1343 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1344 }
1345 break;
caryclark624637c2015-05-11 07:21:27 -07001346 case REC_TYPE_COINCIDENCE:
1347 if (!draw_coincidence) {
1348 break;
1349 }
1350 {
1351 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1352 curve_extremes(curve, angleBounds);
1353 }
1354 break;
caryclarkdac1d172014-06-17 05:15:38 -07001355 case REC_TYPE_SORT:
1356 if (!draw_sort) {
1357 break;
1358 }
1359 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1360 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1361 curve_extremes(curve, angleBounds);
1362 }
1363 break;
caryclark03b03ca2015-04-23 09:13:37 -07001364 case REC_TYPE_TOP:
1365 if (!draw_top) {
1366 break;
1367 }
1368 {
1369 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1370 curve_extremes(curve, angleBounds);
1371 }
1372 break;
caryclarkdac1d172014-06-17 05:15:38 -07001373 }
1374 }
1375 }
1376 xmin = Math.min(xmin, angleBounds[0]);
1377 ymin = Math.min(ymin, angleBounds[1]);
1378 xmax = Math.max(xmax, angleBounds[2]);
1379 ymax = Math.max(ymax, angleBounds[3]);
1380 setScale(xmin, xmax, ymin, ymax);
1381 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001382 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001383 }
1384 if (hasPath == true && hasComputedPath == false && draw_computed) {
1385 draw_computed = 0;
1386 }
1387}
1388
1389function curveByID(test, id) {
caryclark54359292015-03-26 07:52:43 -07001390 var tIndex = -3;
1391 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001392 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001393 if (recType == REC_TYPE_OP) {
1394 continue;
1395 }
1396 if (recType != REC_TYPE_PATH) {
caryclarkdac1d172014-06-17 05:15:38 -07001397 return [];
1398 }
1399 var records = test[tIndex + 2];
1400 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1401 var fragType = records[recordIndex];
1402 var frags = records[recordIndex + 1];
1403 if (frags[0] == id) {
1404 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001405 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001406 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001407 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001408 return [frags[1], frags[2], frags[3], frags[4],
1409 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001410 case PATH_CONIC:
1411 return [frags[1], frags[2], frags[3], frags[4],
1412 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001413 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001414 return [frags[1], frags[2], frags[3], frags[4],
1415 frags[5], frags[6], frags[7], frags[8]];
1416 }
1417 }
1418 }
caryclarkdac1d172014-06-17 05:15:38 -07001419 }
1420 return [];
1421}
1422
1423function curvePartialByID(test, id, t0, t1) {
caryclark54359292015-03-26 07:52:43 -07001424 var tIndex = -3;
1425 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001426 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001427 if (recType == REC_TYPE_OP) {
1428 continue;
1429 }
1430 if (recType != REC_TYPE_PATH) {
caryclarkdac1d172014-06-17 05:15:38 -07001431 return [];
1432 }
1433 var records = test[tIndex + 2];
1434 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1435 var fragType = records[recordIndex];
1436 var frags = records[recordIndex + 1];
1437 if (frags[0] == id) {
1438 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001439 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001440 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001441 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001442 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1443 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001444 case PATH_CONIC:
1445 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1446 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001447 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001448 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1449 frags[5], frags[6], frags[7], frags[8], t0, t1);
1450 }
1451 }
1452 }
caryclarkdac1d172014-06-17 05:15:38 -07001453 }
1454 return [];
1455}
1456
1457function idByCurve(test, frag, type) {
caryclark54359292015-03-26 07:52:43 -07001458 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001459 while (tIndex < test.length) {
1460 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001461 if (recType != REC_TYPE_PATH) {
1462 ++tIndex;
1463 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001464 }
1465 var records = test[tIndex + 2];
1466 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1467 var fragType = records[recordIndex];
1468 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001469 if (frag.length != frags.length - 1) {
1470 continue;
1471 }
caryclarkdac1d172014-06-17 05:15:38 -07001472 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001473 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001474 if (frag[0] != frags[1] || frag[1] != frags[2]
1475 || frag[2] != frags[3] || frag[3] != frags[4]) {
1476 continue;
1477 }
1478 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001479 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001480 if (frag[0] != frags[1] || frag[1] != frags[2]
1481 || frag[2] != frags[3] || frag[3] != frags[4]
1482 || frag[4] != frags[5] || frag[5] != frags[6]) {
1483 continue;
1484 }
1485 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001486 case PATH_CONIC:
1487 if (frag[0] != frags[1] || frag[1] != frags[2]
1488 || frag[2] != frags[3] || frag[3] != frags[4]
1489 || frag[4] != frags[5] || frag[5] != frags[6]
1490 || frag[6] != frags[7]) {
1491 continue;
1492 }
1493 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001494 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001495 if (frag[0] != frags[1] || frag[1] != frags[2]
1496 || frag[2] != frags[3] || frag[3] != frags[4]
1497 || frag[4] != frags[5] || frag[5] != frags[6]
1498 || frag[6] != frags[7] || frag[7] != frags[8]) {
1499 continue;
1500 }
1501 return frags[0];
1502 }
1503 }
1504 ++tIndex;
1505 }
1506 return -1;
1507}
1508
1509function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001510 var length = curve.length == 7 ? 6 : curve.length;
caryclarkdac1d172014-06-17 05:15:38 -07001511 for (var index = 0; index < curve.length; index += 2) {
1512 var x = curve[index];
1513 var y = curve[index + 1];
1514 bounds[0] = Math.min(bounds[0], x);
1515 bounds[1] = Math.min(bounds[1], y);
1516 bounds[2] = Math.max(bounds[2], x);
1517 bounds[3] = Math.max(bounds[3], y);
1518 }
1519}
1520
1521function setScale(x0, x1, y0, y1) {
1522 var srcWidth = x1 - x0;
1523 var srcHeight = y1 - y0;
1524 var usableWidth = screenWidth;
1525 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1526 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1527 usableWidth -= (xDigits + yDigits) * 10;
1528 usableWidth -= decimal_places * 10;
1529 if (draw_legend) {
1530 usableWidth -= 40;
1531 }
1532 var hscale = usableWidth / srcWidth;
1533 var vscale = screenHeight / srcHeight;
1534 scale = Math.min(hscale, vscale);
1535 var invScale = 1 / scale;
1536 var sxmin = x0 - invScale * 5;
1537 var symin = y0 - invScale * 10;
1538 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1539 var symax = y1 + invScale * 10;
1540 srcWidth = sxmax - sxmin;
1541 srcHeight = symax - symin;
1542 hscale = usableWidth / srcWidth;
1543 vscale = screenHeight / srcHeight;
1544 scale = Math.min(hscale, vscale);
1545 srcLeft = sxmin;
1546 srcTop = symin;
1547}
1548
1549function drawArc(curve, op, from, to) {
1550 var type = PATH_LINE + (curve.length / 2 - 2);
1551 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1552 var dy = pt.y - curve[1];
1553 var dx = pt.x - curve[0];
1554 var dist = Math.sqrt(dy * dy + dx * dx);
1555 var _dist = dist * scale;
1556 var angle = Math.atan2(dy, dx);
1557 var _px = (curve[0] - srcLeft) * scale;
1558 var _py = (curve[1] - srcTop) * scale;
1559 var divisor = 4;
1560 var endDist;
1561 do {
1562 var ends = [];
1563 for (var index = -1; index <= 1; index += 2) {
1564 var px = Math.cos(index * Math.PI / divisor);
1565 var py = Math.sin(index * Math.PI / divisor);
1566 ends.push(px);
1567 ends.push(py);
1568 }
1569 var endDx = (ends[2] - ends[0]) * scale * dist;
1570 var endDy = (ends[3] - ends[1]) * scale * dist;
1571 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1572 if (endDist < 100) {
1573 break;
1574 }
1575 divisor *= 2;
1576 } while (true);
1577 if (endDist < 30) {
1578 return;
1579 }
1580 if (op) {
1581 divisor *= 2;
1582 }
1583 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1584 ctx.beginPath();
1585 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1586 ctx.stroke();
1587 var saveAlign = ctx.textAlign;
1588 var saveStyle = ctx.fillStyle;
1589 var saveFont = ctx.font;
1590 ctx.textAlign = "center";
1591 ctx.fillStyle = "black";
1592 ctx.font = "normal 24px Arial";
1593 divisor *= 0.8;
1594 for (var index = -1; index <= 1; index += 2) {
1595 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1596 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1597 var _px = (px - srcLeft) * scale;
1598 var _py = (py - srcTop) * scale;
1599 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1600 }
1601 ctx.textAlign = saveAlign;
1602 ctx.fillStyle = saveStyle;
1603 ctx.font = saveFont;
1604}
1605
1606function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001607 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1608 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001609 var x = drawnPts[pts];
1610 var y = drawnPts[pts + 1];
1611 if (px == x && py == y) {
1612 return;
1613 }
1614 }
1615 drawnPts.push(px);
1616 drawnPts.push(py);
1617 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1618 var _px = (px - srcLeft) * scale;
1619 var _py = (py - srcTop) * scale;
1620 ctx.beginPath();
1621 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1622 ctx.closePath();
1623 if (end) {
1624 ctx.fill();
1625 } else {
1626 ctx.stroke();
1627 }
1628 if (debug_xy) {
1629 ctx.textAlign = "left";
1630 ctx.fillText(label, _px + 5, _py);
1631 }
1632}
1633
caryclark1049f122015-04-20 08:31:59 -07001634function coordCount(curveType) {
1635 switch (curveType) {
1636 case PATH_LINE:
1637 return 4;
1638 case PATH_QUAD:
1639 return 6;
1640 case PATH_CONIC:
1641 return 6;
1642 case PATH_CUBIC:
1643 return 8;
1644 }
1645 return -1;
1646}
1647
caryclarkdac1d172014-06-17 05:15:38 -07001648function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001649 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001650 for (var idx = 0; idx < count; idx += 2) {
1651 if (!drawControls && idx != 0 && idx != count - 2) {
1652 continue;
1653 }
1654 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1655 }
1656}
1657
1658function drawControlLines(curve, curveType, drawEnd) {
1659 if (curveType == PATH_LINE) {
1660 return;
1661 }
1662 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1663 drawLine(curve[0], curve[1], curve[2], curve[3]);
1664 drawLine(curve[2], curve[3], curve[4], curve[5]);
1665 if (curveType == PATH_CUBIC) {
1666 drawLine(curve[4], curve[5], curve[6], curve[7]);
1667 if (drawEnd > 1) {
1668 drawLine(curve[6], curve[7], curve[0], curve[1]);
1669 if (drawEnd > 2) {
1670 drawLine(curve[0], curve[1], curve[4], curve[5]);
1671 drawLine(curve[6], curve[7], curve[2], curve[3]);
1672 }
1673 }
1674 } else if (drawEnd > 1) {
1675 drawLine(curve[4], curve[5], curve[0], curve[1]);
1676 }
1677}
1678
1679function pointAtT(curve, curveType, t) {
1680 var xy = {};
1681 switch (curveType) {
1682 case PATH_LINE:
1683 var a = 1 - t;
1684 var b = t;
1685 xy.x = a * curve[0] + b * curve[2];
1686 xy.y = a * curve[1] + b * curve[3];
1687 break;
1688 case PATH_QUAD:
1689 var one_t = 1 - t;
1690 var a = one_t * one_t;
1691 var b = 2 * one_t * t;
1692 var c = t * t;
1693 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1694 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1695 break;
caryclark1049f122015-04-20 08:31:59 -07001696 case PATH_CONIC:
1697 var one_t = 1 - t;
1698 var a = one_t * one_t;
1699 var b = 2 * one_t * t;
1700 var c = t * t;
1701 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1702 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1703 var d = a + b * curve[6] + c;
1704 xy.x /= d;
1705 xy.y /= d;
1706 break;
caryclarkdac1d172014-06-17 05:15:38 -07001707 case PATH_CUBIC:
1708 var one_t = 1 - t;
1709 var one_t2 = one_t * one_t;
1710 var a = one_t2 * one_t;
1711 var b = 3 * one_t2 * t;
1712 var t2 = t * t;
1713 var c = 3 * one_t * t2;
1714 var d = t2 * t;
1715 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1716 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1717 break;
1718 }
1719 return xy;
1720}
1721
1722function drawPointAtT(curve, curveType) {
1723 var x, y;
1724 var xy = pointAtT(curve, curveType, curveT);
1725 drawPoint(xy.x, xy.y, true);
1726 if (!draw_intersectT) {
1727 return;
1728 }
1729 ctx.fillStyle = "red";
1730 drawTAtPointUp(xy.x, xy.y, curveT);
1731}
1732
1733function drawTAtPointUp(px, py, t) {
1734 var label = t.toFixed(decimal_places);
1735 var _px = (px - srcLeft)* scale;
1736 var _py = (py - srcTop) * scale;
1737 ctx.fillText(label, _px + 5, _py - 10);
1738}
1739
1740function drawTAtPointDown(px, py, t) {
1741 var label = t.toFixed(decimal_places);
1742 var _px = (px - srcLeft)* scale;
1743 var _py = (py - srcTop) * scale;
1744 ctx.fillText(label, _px + 5, _py + 10);
1745}
1746
1747function alreadyDrawnLine(x1, y1, x2, y2) {
1748 if (collect_bounds) {
1749 if (focus_enabled) {
1750 focusXmin = Math.min(focusXmin, x1, x2);
1751 focusYmin = Math.min(focusYmin, y1, y2);
1752 focusXmax = Math.max(focusXmax, x1, x2);
1753 focusYmax = Math.max(focusYmax, y1, y2);
1754 }
1755 return true;
1756 }
1757 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1758 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1759 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1760 return true;
1761 }
1762 }
1763 drawnLines.push(x1);
1764 drawnLines.push(y1);
1765 drawnLines.push(x2);
1766 drawnLines.push(y2);
1767 return false;
1768}
1769
1770function drawLine(x1, y1, x2, y2) {
1771 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1772 return;
1773 }
1774 ctx.beginPath();
1775 ctx.moveTo((x1 - srcLeft) * scale,
1776 (y1 - srcTop) * scale);
1777 ctx.lineTo((x2 - srcLeft) * scale,
1778 (y2 - srcTop) * scale);
1779 ctx.stroke();
1780}
1781
1782function linePartial(x1, y1, x2, y2, t1, t2) {
1783 var dx = x1 - x2;
1784 var dy = y1 - y2;
1785 var array = [
1786 x1 - t1 * dx,
1787 y1 - t1 * dy,
1788 x1 - t2 * dx,
1789 y1 - t2 * dy
1790 ];
1791 return array;
1792}
1793
1794function drawLinePartial(x1, y1, x2, y2, t1, t2) {
1795 var a = linePartial(x1, y1, x2, y2, t1, t2);
1796 var ax = a[0];
1797 var ay = a[1];
1798 var bx = a[2];
1799 var by = a[3];
1800 if (alreadyDrawnLine(ax, ay, bx, by)) {
1801 return;
1802 }
1803 ctx.beginPath();
1804 ctx.moveTo((ax - srcLeft) * scale,
1805 (ay - srcTop) * scale);
1806 ctx.lineTo((bx - srcLeft) * scale,
1807 (by - srcTop) * scale);
1808 ctx.stroke();
1809}
1810
1811function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
1812 if (collect_bounds) {
1813 if (focus_enabled) {
1814 focusXmin = Math.min(focusXmin, x1, x2, x3);
1815 focusYmin = Math.min(focusYmin, y1, y2, y3);
1816 focusXmax = Math.max(focusXmax, x1, x2, x3);
1817 focusYmax = Math.max(focusYmax, y1, y2, y3);
1818 }
1819 return true;
1820 }
1821 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
1822 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
1823 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
1824 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
1825 return true;
1826 }
1827 }
1828 drawnQuads.push(x1);
1829 drawnQuads.push(y1);
1830 drawnQuads.push(x2);
1831 drawnQuads.push(y2);
1832 drawnQuads.push(x3);
1833 drawnQuads.push(y3);
1834 return false;
1835}
1836
1837function drawQuad(x1, y1, x2, y2, x3, y3) {
1838 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
1839 return;
1840 }
1841 ctx.beginPath();
1842 ctx.moveTo((x1 - srcLeft) * scale,
1843 (y1 - srcTop) * scale);
1844 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
1845 (y2 - srcTop) * scale,
1846 (x3 - srcLeft) * scale,
1847 (y3 - srcTop) * scale);
1848 ctx.stroke();
1849}
1850
1851function interp(A, B, t) {
1852 return A + (B - A) * t;
1853}
1854
1855function interp_quad_coords(x1, x2, x3, t)
1856{
1857 var ab = interp(x1, x2, t);
1858 var bc = interp(x2, x3, t);
1859 var abc = interp(ab, bc, t);
1860 return abc;
1861}
1862
1863function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1864 var ax = interp_quad_coords(x1, x2, x3, t1);
1865 var ay = interp_quad_coords(y1, y2, y3, t1);
1866 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
1867 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
1868 var cx = interp_quad_coords(x1, x2, x3, t2);
1869 var cy = interp_quad_coords(y1, y2, y3, t2);
1870 var bx = 2*dx - (ax + cx)/2;
1871 var by = 2*dy - (ay + cy)/2;
1872 var array = [
1873 ax, ay, bx, by, cx, cy
1874 ];
1875 return array;
1876}
1877
1878function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1879 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
1880 var ax = a[0];
1881 var ay = a[1];
1882 var bx = a[2];
1883 var by = a[3];
1884 var cx = a[4];
1885 var cy = a[5];
1886 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
1887 return;
1888 }
1889 ctx.beginPath();
1890 ctx.moveTo((ax - srcLeft) * scale,
1891 (ay - srcTop) * scale);
1892 ctx.quadraticCurveTo((bx - srcLeft) * scale,
1893 (by - srcTop) * scale,
1894 (cx - srcLeft) * scale,
1895 (cy - srcTop) * scale);
1896 ctx.stroke();
1897}
1898
caryclark1049f122015-04-20 08:31:59 -07001899function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
1900 if (collect_bounds) {
1901 if (focus_enabled) {
1902 focusXmin = Math.min(focusXmin, x1, x2, x3);
1903 focusYmin = Math.min(focusYmin, y1, y2, y3);
1904 focusXmax = Math.max(focusXmax, x1, x2, x3);
1905 focusYmax = Math.max(focusYmax, y1, y2, y3);
1906 }
1907 return true;
1908 }
1909 for (var pts = 0; pts < drawnConics.length; pts += 8) {
1910 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
1911 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1912 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1913 && w == drawnCubics[pts + 6]) {
1914 return true;
1915 }
1916 }
1917 drawnConics.push(x1);
1918 drawnConics.push(y1);
1919 drawnConics.push(x2);
1920 drawnConics.push(y2);
1921 drawnConics.push(x3);
1922 drawnConics.push(y3);
1923 drawnCubics.push(w);
1924 return false;
1925}
1926
1927var kMaxConicToQuadPOW2 = 5;
1928
1929function computeQuadPOW2(curve, tol) {
1930 var a = curve[6] - 1;
1931 var k = a / (4 * (2 + a));
1932 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
1933 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
1934
1935 var error = Math.sqrt(x * x + y * y);
1936 var pow2;
1937 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
1938 if (error <= tol) {
1939 break;
1940 }
1941 error *= 0.25;
1942 }
1943 return pow2;
1944}
1945
1946function subdivide_w_value(w) {
1947 return Math.sqrt(0.5 + w * 0.5);
1948}
1949
1950function chop(curve, part1, part2) {
1951 var w = curve[6];
1952 var scale = 1 / (1 + w);
1953 part1[0] = curve[0];
1954 part1[1] = curve[1];
1955 part1[2] = (curve[0] + curve[2] * w) * scale;
1956 part1[3] = (curve[1] + curve[3] * w) * scale;
1957 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
1958 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
1959 part2[2] = (curve[2] * w + curve[4]) * scale;
1960 part2[3] = (curve[3] * w + curve[5]) * scale;
1961 part2[4] = curve[4];
1962 part2[5] = curve[5];
1963 part1[6] = part2[6] = subdivide_w_value(w);
1964}
1965
1966function subdivide(curve, level, pts) {
1967 if (0 == level) {
1968 pts.push(curve[2]);
1969 pts.push(curve[3]);
1970 pts.push(curve[4]);
1971 pts.push(curve[5]);
1972 } else {
1973 var part1 = [], part2 = [];
1974 chop(curve, part1, part2);
1975 --level;
1976 subdivide(part1, level, pts);
1977 subdivide(part2, level, pts);
1978 }
1979}
1980
1981function chopIntoQuadsPOW2(curve, pow2, pts) {
1982 subdivide(curve, pow2, pts);
1983 return 1 << pow2;
1984}
1985
1986function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
1987 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
1988 return;
1989 }
1990 ctx.beginPath();
1991 ctx.moveTo((x1 - srcLeft) * scale,
1992 (y1 - srcTop) * scale);
1993 var tol = 1 / scale;
1994 var curve = [x1, y1, x2, y2, x3, y3, w];
1995 var pow2 = computeQuadPOW2(curve, tol);
1996 var pts = [];
1997 chopIntoQuadsPOW2(curve, pow2, pts);
1998 for (var i = 0; i < pts.length; i += 4) {
1999 ctx.quadraticCurveTo(
2000 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
2001 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
2002 }
2003 ctx.stroke();
2004}
2005
2006function conic_eval_numerator(x1, x2, x3, w, t) {
2007 var src2w = x2 * w;
2008 var C = x1;
2009 var A = x3 - 2 * src2w + C;
2010 var B = 2 * (src2w - C);
2011 return (A * t + B) * t + C;
2012}
2013
2014
2015function conic_eval_denominator(w, t) {
2016 var B = 2 * (w - 1);
2017 var C = 1;
2018 var A = -B;
2019 return (A * t + B) * t + C;
2020}
2021
2022function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2023 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
2024 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
2025 var az = conic_eval_denominator(w, t1);
2026 var midT = (t1 + t2) / 2;
2027 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
2028 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
2029 var dz = conic_eval_denominator(w, midT);
2030 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
2031 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
2032 var cz = conic_eval_denominator(w, t2);
2033 var bx = 2 * dx - (ax + cx) / 2;
2034 var by = 2 * dy - (ay + cy) / 2;
2035 var bz = 2 * dz - (az + cz) / 2;
2036 var dt = t2 - t1;
2037 var dt_1 = 1 - dt;
2038 var partW = (1 + dt * (w - 1)) / Math.sqrt(dt * dt + 2 * dt * dt_1 * w + dt_1 * dt_1);
2039 var array = [
2040 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, partW
2041 ];
2042 return array;
2043}
2044
2045function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2046 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2047 var ax = a[0];
2048 var ay = a[1];
2049 var bx = a[2];
2050 var by = a[3];
2051 var cx = a[4];
2052 var cy = a[5];
2053 var w_ = a[6];
2054 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
2055}
2056
caryclarkdac1d172014-06-17 05:15:38 -07002057function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2058 if (collect_bounds) {
2059 if (focus_enabled) {
2060 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
2061 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
2062 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
2063 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
2064 }
2065 return true;
2066 }
2067 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
2068 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
2069 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2070 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
2071 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
2072 return true;
2073 }
2074 }
2075 drawnCubics.push(x1);
2076 drawnCubics.push(y1);
2077 drawnCubics.push(x2);
2078 drawnCubics.push(y2);
2079 drawnCubics.push(x3);
2080 drawnCubics.push(y3);
2081 drawnCubics.push(x4);
2082 drawnCubics.push(y4);
2083 return false;
2084}
2085
2086function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2087 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
2088 return;
2089 }
2090 ctx.beginPath();
2091 ctx.moveTo((x1 - srcLeft) * scale,
2092 (y1 - srcTop) * scale);
2093 ctx.bezierCurveTo((x2 - srcLeft) * scale,
2094 (y2 - srcTop) * scale,
2095 (x3 - srcLeft) * scale,
2096 (y3 - srcTop) * scale,
2097 (x4 - srcLeft) * scale,
2098 (y4 - srcTop) * scale);
2099 ctx.stroke();
2100}
2101
2102function interp_cubic_coords(x1, x2, x3, x4, t)
2103{
2104 var ab = interp(x1, x2, t);
2105 var bc = interp(x2, x3, t);
2106 var cd = interp(x3, x4, t);
2107 var abc = interp(ab, bc, t);
2108 var bcd = interp(bc, cd, t);
2109 var abcd = interp(abc, bcd, t);
2110 return abcd;
2111}
2112
2113function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2114 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
2115 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
2116 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
2117 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
2118 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
2119 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
2120 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
2121 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
2122 var mx = ex * 27 - ax * 8 - dx;
2123 var my = ey * 27 - ay * 8 - dy;
2124 var nx = fx * 27 - ax - dx * 8;
2125 var ny = fy * 27 - ay - dy * 8;
2126 var bx = (mx * 2 - nx) / 18;
2127 var by = (my * 2 - ny) / 18;
2128 var cx = (nx * 2 - mx) / 18;
2129 var cy = (ny * 2 - my) / 18;
2130 var array = [
2131 ax, ay, bx, by, cx, cy, dx, dy
2132 ];
2133 return array;
2134}
2135
2136function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2137 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2138 var ax = a[0];
2139 var ay = a[1];
2140 var bx = a[2];
2141 var by = a[3];
2142 var cx = a[4];
2143 var cy = a[5];
2144 var dx = a[6];
2145 var dy = a[7];
2146 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
2147 return;
2148 }
2149 ctx.beginPath();
2150 ctx.moveTo((ax - srcLeft) * scale,
2151 (ay - srcTop) * scale);
2152 ctx.bezierCurveTo((bx - srcLeft) * scale,
2153 (by - srcTop) * scale,
2154 (cx - srcLeft) * scale,
2155 (cy - srcTop) * scale,
2156 (dx - srcLeft) * scale,
2157 (dy - srcTop) * scale);
2158 ctx.stroke();
2159}
2160
2161function drawCurve(c) {
2162 switch (c.length) {
2163 case 4:
2164 drawLine(c[0], c[1], c[2], c[3]);
2165 break;
2166 case 6:
2167 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
2168 break;
caryclark1049f122015-04-20 08:31:59 -07002169 case 7:
2170 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
2171 break;
caryclarkdac1d172014-06-17 05:15:38 -07002172 case 8:
2173 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
2174 break;
2175 }
2176}
2177
2178function boundsWidth(pts) {
2179 var min = pts[0];
2180 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07002181 var length = pts.length == 7 ? 6 : pts.length;
2182 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002183 min = Math.min(min, pts[idx]);
2184 max = Math.max(max, pts[idx]);
2185 }
2186 return max - min;
2187}
2188
2189function boundsHeight(pts) {
2190 var min = pts[1];
2191 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07002192 var length = pts.length == 7 ? 6 : pts.length;
2193 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002194 min = Math.min(min, pts[idx]);
2195 max = Math.max(max, pts[idx]);
2196 }
2197 return max - min;
2198}
2199
2200function tangent(pts) {
2201 var dx = pts[2] - pts[0];
2202 var dy = pts[3] - pts[1];
2203 if (dx == 0 && dy == 0 && pts.length > 4) {
2204 dx = pts[4] - pts[0];
2205 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002206 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002207 dx = pts[6] - pts[0];
2208 dy = pts[7] - pts[1];
2209 }
2210 }
2211 return Math.atan2(-dy, dx);
2212}
2213
2214function hodograph(cubic) {
2215 var hodo = [];
2216 hodo[0] = 3 * (cubic[2] - cubic[0]);
2217 hodo[1] = 3 * (cubic[3] - cubic[1]);
2218 hodo[2] = 3 * (cubic[4] - cubic[2]);
2219 hodo[3] = 3 * (cubic[5] - cubic[3]);
2220 hodo[4] = 3 * (cubic[6] - cubic[4]);
2221 hodo[5] = 3 * (cubic[7] - cubic[5]);
2222 return hodo;
2223}
2224
2225function hodograph2(cubic) {
2226 var quad = hodograph(cubic);
2227 var hodo = [];
2228 hodo[0] = 2 * (quad[2] - quad[0]);
2229 hodo[1] = 2 * (quad[3] - quad[1]);
2230 hodo[2] = 2 * (quad[4] - quad[2]);
2231 hodo[3] = 2 * (quad[5] - quad[3]);
2232 return hodo;
2233}
2234
2235function quadraticRootsReal(A, B, C, s) {
2236 if (A == 0) {
2237 if (B == 0) {
2238 s[0] = 0;
2239 return C == 0;
2240 }
2241 s[0] = -C / B;
2242 return 1;
2243 }
2244 /* normal form: x^2 + px + q = 0 */
2245 var p = B / (2 * A);
2246 var q = C / A;
2247 var p2 = p * p;
2248 if (p2 < q) {
2249 return 0;
2250 }
2251 var sqrt_D = 0;
2252 if (p2 > q) {
2253 sqrt_D = sqrt(p2 - q);
2254 }
2255 s[0] = sqrt_D - p;
2256 s[1] = -sqrt_D - p;
2257 return 1 + s[0] != s[1];
2258}
2259
2260function add_valid_ts(s, realRoots, t) {
2261 var foundRoots = 0;
2262 for (var index = 0; index < realRoots; ++index) {
2263 var tValue = s[index];
2264 if (tValue >= 0 && tValue <= 1) {
2265 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2266 if (t[idx2] != tValue) {
2267 t[foundRoots++] = tValue;
2268 }
2269 }
2270 }
2271 }
2272 return foundRoots;
2273}
2274
2275function quadraticRootsValidT(a, b, c, t) {
2276 var s = [];
2277 var realRoots = quadraticRootsReal(A, B, C, s);
2278 var foundRoots = add_valid_ts(s, realRoots, t);
2279 return foundRoots != 0;
2280}
2281
2282function find_cubic_inflections(cubic, tValues) {
2283 var Ax = src[2] - src[0];
2284 var Ay = src[3] - src[1];
2285 var Bx = src[4] - 2 * src[2] + src[0];
2286 var By = src[5] - 2 * src[3] + src[1];
2287 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2288 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2289 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2290 Ax * By - Ay * Bx, tValues);
2291}
2292
2293function dxy_at_t(curve, type, t) {
2294 var dxy = {};
2295 if (type == PATH_QUAD) {
2296 var a = t - 1;
2297 var b = 1 - 2 * t;
2298 var c = t;
2299 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2300 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002301 } else if (type == PATH_CONIC) {
2302 var p20x = curve[4] - curve[0];
2303 var p20y = curve[5] - curve[1];
2304 var p10xw = (curve[2] - curve[0]) * curve[6];
2305 var p10yw = (curve[3] - curve[1]) * curve[6];
2306 var coeff0x = curve[6] * p20x - p20x;
2307 var coeff0y = curve[6] * p20y - p20y;
2308 var coeff1x = p20x - 2 * p10xw;
2309 var coeff1y = p20y - 2 * p10yw;
2310 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2311 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002312 } else if (type == PATH_CUBIC) {
2313 var one_t = 1 - t;
2314 var a = curve[0];
2315 var b = curve[2];
2316 var c = curve[4];
2317 var d = curve[6];
2318 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2319 a = curve[1];
2320 b = curve[3];
2321 c = curve[5];
2322 d = curve[7];
2323 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2324 }
2325 return dxy;
2326}
2327
2328function drawLabel(num, px, py) {
2329 ctx.beginPath();
2330 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2331 ctx.closePath();
2332 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2333 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2334 ctx.stroke();
2335 ctx.fillStyle = "black";
2336 ctx.font = "normal 10px Arial";
2337 // ctx.rotate(0.001);
2338 ctx.fillText(num, px - 2, py + 3);
2339 // ctx.rotate(-0.001);
2340}
2341
2342function drawLabelX(ymin, num, loc) {
2343 var px = (loc - srcLeft) * scale;
2344 var py = (ymin - srcTop) * scale - 20;
2345 drawLabel(num, px, py);
2346}
2347
2348function drawLabelY(xmin, num, loc) {
2349 var px = (xmin - srcLeft) * scale - 20;
2350 var py = (loc - srcTop) * scale;
2351 drawLabel(num, px, py);
2352}
2353
2354function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2355 ctx.beginPath();
2356 ctx.moveTo(hx, hy - 100);
2357 ctx.lineTo(hx, hy);
2358 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2359 ctx.stroke();
2360 ctx.beginPath();
2361 ctx.moveTo(hx, hy);
2362 ctx.lineTo(hx, hy + 100);
2363 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2364 ctx.stroke();
2365 ctx.beginPath();
2366 ctx.moveTo(hx - 100, hy);
2367 ctx.lineTo(hx, hy);
2368 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2369 ctx.stroke();
2370 ctx.beginPath();
2371 ctx.moveTo(hx, hy);
2372 ctx.lineTo(hx + 100, hy);
2373 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2374 ctx.stroke();
2375}
2376
2377function scalexy(x, y, mag) {
2378 var length = Math.sqrt(x * x + y * y);
2379 return mag / length;
2380}
2381
caryclark03b03ca2015-04-23 09:13:37 -07002382function drawArrow(x, y, dx, dy, s) {
2383 var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
caryclarkdac1d172014-06-17 05:15:38 -07002384 dx *= dscale;
2385 dy *= dscale;
2386 ctx.beginPath();
2387 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2388 x += dx;
2389 y += dy;
2390 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2391 dx /= 10;
2392 dy /= 10;
2393 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2394 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2395 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2396 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2397 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2398 ctx.stroke();
2399}
2400
2401function x_at_t(curve, t) {
2402 var one_t = 1 - t;
2403 if (curve.length == 4) {
2404 return one_t * curve[0] + t * curve[2];
2405 }
2406 var one_t2 = one_t * one_t;
2407 var t2 = t * t;
2408 if (curve.length == 6) {
2409 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2410 }
caryclark1049f122015-04-20 08:31:59 -07002411 if (curve.length == 7) {
2412 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2413 / (one_t2 +2 * one_t * t * curve[6] + t2);
2414 }
caryclarkdac1d172014-06-17 05:15:38 -07002415 var a = one_t2 * one_t;
2416 var b = 3 * one_t2 * t;
2417 var c = 3 * one_t * t2;
2418 var d = t2 * t;
2419 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2420}
2421
2422function y_at_t(curve, t) {
2423 var one_t = 1 - t;
2424 if (curve.length == 4) {
2425 return one_t * curve[1] + t * curve[3];
2426 }
2427 var one_t2 = one_t * one_t;
2428 var t2 = t * t;
2429 if (curve.length == 6) {
2430 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2431 }
caryclark1049f122015-04-20 08:31:59 -07002432 if (curve.length == 7) {
2433 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2434 / (one_t2 +2 * one_t * t * curve[6] + t2);
2435 }
caryclarkdac1d172014-06-17 05:15:38 -07002436 var a = one_t2 * one_t;
2437 var b = 3 * one_t2 * t;
2438 var c = 3 * one_t * t2;
2439 var d = t2 * t;
2440 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2441}
2442
2443function drawOrder(curve, label) {
2444 var px = x_at_t(curve, 0.75);
2445 var py = y_at_t(curve, 0.75);
2446 var _px = (px - srcLeft) * scale;
2447 var _py = (py - srcTop) * scale;
2448 ctx.beginPath();
2449 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2450 ctx.closePath();
2451 ctx.fillStyle = "white";
2452 ctx.fill();
2453 if (label == 'L') {
2454 ctx.strokeStyle = "rgba(255,0,0, 1)";
2455 ctx.fillStyle = "rgba(255,0,0, 1)";
2456 } else {
2457 ctx.strokeStyle = "rgba(0,0,255, 1)";
2458 ctx.fillStyle = "rgba(0,0,255, 1)";
2459 }
2460 ctx.stroke();
2461 ctx.font = "normal 16px Arial";
2462 ctx.textAlign = "center";
2463 ctx.fillText(label, _px, _py + 5);
2464 ctx.font = "normal 10px Arial";
2465}
2466
2467function drawID(curve, id) {
2468 var px = x_at_t(curve, 0.5);
2469 var py = y_at_t(curve, 0.5);
2470 var _px = (px - srcLeft) * scale;
2471 var _py = (py - srcTop) * scale;
2472 draw_id_at(id, _px, _py);
2473}
2474
2475function draw_id_at(id, _px, _py) {
2476 ctx.beginPath();
2477 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2478 ctx.closePath();
2479 ctx.fillStyle = "white";
2480 ctx.fill();
2481 ctx.strokeStyle = "rgba(127,127,0, 1)";
2482 ctx.fillStyle = "rgba(127,127,0, 1)";
2483 ctx.stroke();
2484 ctx.font = "normal 16px Arial";
2485 ctx.textAlign = "center";
2486 ctx.fillText(id, _px, _py + 5);
2487 ctx.font = "normal 10px Arial";
2488}
2489
2490function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2491 var curve = [x1, y1, x2, y2];
2492 drawCurvePartialID(id, curve, t1, t2);
2493}
2494
2495function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2496 var curve = [x1, y1, x2, y2, x3, y3];
2497 drawCurvePartialID(id, curve, t1, t2);
2498}
2499
caryclark1049f122015-04-20 08:31:59 -07002500function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2501 var curve = [x1, y1, x2, y2, x3, y3, w];
2502 drawCurvePartialID(id, curve, t1, t2);
2503}
2504
caryclarkdac1d172014-06-17 05:15:38 -07002505function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2506 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2507 drawCurvePartialID(id, curve, t1, t2);
2508}
2509
2510function drawCurvePartialID(id, curve, t1, t2) {
2511 var px = x_at_t(curve, (t1 + t2) / 2);
2512 var py = y_at_t(curve, (t1 + t2) / 2);
2513 var _px = (px - srcLeft) * scale;
2514 var _py = (py - srcTop) * scale;
2515 draw_id_at(id, _px, _py);
2516}
2517
2518function drawCurveSpecials(test, curve, type) {
2519 if (pt_labels) {
2520 drawPoints(curve, type, pt_labels == 2);
2521 }
2522 if (control_lines != 0) {
2523 drawControlLines(curve, type, control_lines);
2524 }
2525 if (curve_t) {
2526 drawPointAtT(curve, type);
2527 }
2528 if (draw_midpoint) {
2529 var mid = pointAtT(curve, type, 0.5);
2530 drawPoint(mid.x, mid.y, true);
2531 }
2532 if (draw_id) {
2533 var id = idByCurve(test, curve, type);
2534 if (id >= 0) {
2535 drawID(curve, id);
2536 }
2537 }
2538 if (type == PATH_LINE) {
2539 return;
2540 }
2541 if (draw_deriviatives > 0) {
2542 var d = dxy_at_t(curve, type, 0);
caryclark03b03ca2015-04-23 09:13:37 -07002543 drawArrow(curve[0], curve[1], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002544 if (draw_deriviatives == 2) {
2545 d = dxy_at_t(curve, type, 1);
2546 if (type == PATH_CUBIC) {
caryclark03b03ca2015-04-23 09:13:37 -07002547 drawArrow(curve[6], curve[7], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002548 } else {
caryclark03b03ca2015-04-23 09:13:37 -07002549 drawArrow(curve[4], curve[5], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002550 }
2551 }
2552 if (draw_midpoint) {
2553 var mid = pointAtT(curve, type, 0.5);
2554 d = dxy_at_t(curve, type, 0.5);
caryclark03b03ca2015-04-23 09:13:37 -07002555 drawArrow(mid.x, mid.y, d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002556 }
2557 }
2558 if (type != PATH_CUBIC) {
2559 return;
2560 }
caryclarkdac1d172014-06-17 05:15:38 -07002561 if (draw_sequence) {
2562 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2563 for (var i = 0; i < 8; i+= 2) {
2564 drawLabelX(ymin, i >> 1, curve[i]);
2565 }
2566 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2567 for (var i = 1; i < 8; i+= 2) {
2568 drawLabelY(xmin, i >> 1, curve[i]);
2569 }
2570 }
2571}
2572
2573function logCurves(test) {
2574 for (curves in test) {
2575 var curve = test[curves];
2576 dumpCurve(curve);
2577 }
2578}
2579
2580function curveToString(curve) {
2581 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002582 var length = curve.length == 7 ? 6 : curve.length;
2583 if (curve.length == 7) {
2584 str += "{";
2585 }
2586 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002587 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2588 if (i < curve.length - 2) {
2589 str += "}, {";
2590 }
2591 }
caryclark1049f122015-04-20 08:31:59 -07002592 str += "}";
2593 if (curve.length == 7) {
2594 str += "}, " + curve[6].toFixed(decimal_places);
2595 }
2596 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07002597 return str;
2598}
2599
2600function dumpCurve(curve) {
2601 console.log(curveToString(curve));
2602}
2603
2604function draw(test, lines, title) {
2605 ctx.fillStyle = "rgba(0,0,0, 0.1)";
2606 ctx.font = "normal 50px Arial";
2607 ctx.textAlign = "left";
2608 ctx.fillText(title, 50, 50);
2609 ctx.font = "normal 10px Arial";
2610 ctx.lineWidth = "1.001"; "0.999";
2611 var secondPath = test.length;
2612 var closeCount = 0;
2613 logStart = -1;
2614 logRange = 0;
2615 // find last active rec type at this step
2616 var curType = test[0];
2617 var curStep = 0;
2618 var hasOp = false;
2619 var lastActive = 0;
2620 var lastAdd = 0;
caryclark624637c2015-05-11 07:21:27 -07002621 var lastCoin = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002622 var lastSect = 0;
2623 var lastSort = 0;
2624 var lastMark = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002625 var lastTop = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002626 activeCount = 0;
2627 addCount = 0;
2628 angleCount = 0;
2629 opCount = 0;
2630 sectCount = 0;
2631 sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002632 topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002633 markCount = 0;
2634 activeMax = 0;
2635 addMax = 0;
2636 angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -07002637 coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002638 opMax = 0;
2639 sectMax = 0;
2640 sectMax2 = 0;
2641 sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002642 topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002643 markMax = 0;
2644 lastIndex = test.length - 3;
2645 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
2646 var recType = test[tIndex];
2647 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
2648 console.log("unknown rec type: " + recType);
2649 throw "stop execution";
2650 }
2651 // if (curType == recType && curType != REC_TYPE_ADD) {
2652 // continue;
2653 // }
2654 var inStepRange = step_limit == 0 || curStep < step_limit;
2655 curType = recType;
2656 if (recType == REC_TYPE_OP) {
2657 hasOp = true;
2658 continue;
2659 }
2660 if (recType == REC_TYPE_UNKNOWN) {
2661 // these types do not advance step
2662 continue;
2663 }
2664 var bumpStep = false;
2665 var records = test[tIndex + 2];
2666 var fragType = records[0];
2667 if (recType == REC_TYPE_ADD) {
2668 if (records.length != 2) {
2669 console.log("expect only two elements: " + records.length);
2670 throw "stop execution";
2671 }
2672 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
2673 continue;
2674 }
2675 ++addMax;
2676 if (!draw_add || !inStepRange) {
2677 continue;
2678 }
2679 lastAdd = tIndex;
2680 ++addCount;
2681 bumpStep = true;
2682 }
2683 if (recType == REC_TYPE_PATH && hasOp) {
2684 secondPath = tIndex;
2685 }
caryclark54359292015-03-26 07:52:43 -07002686 if (recType == REC_TYPE_PATH2 && hasOp) {
2687 secondPath = tIndex;
2688 }
caryclarkdac1d172014-06-17 05:15:38 -07002689 if (recType == REC_TYPE_ACTIVE) {
2690 ++activeMax;
2691 if (!draw_active || !inStepRange) {
2692 continue;
2693 }
2694 lastActive = tIndex;
2695 ++activeCount;
2696 bumpStep = true;
2697 }
2698 if (recType == REC_TYPE_ACTIVE_OP) {
2699 ++opMax;
2700 if (!draw_op || !inStepRange) {
2701 continue;
2702 }
2703 lastOp = tIndex;
2704 ++opCount;
2705 bumpStep = true;
2706 }
caryclark54359292015-03-26 07:52:43 -07002707 if (recType == REC_TYPE_AFTERPART) {
2708 if (draw_angle != 3 || !inStepRange) {
2709 continue;
2710 }
2711 lastAngle = tIndex;
2712 ++angleCount;
2713 bumpStep = true;
2714 }
caryclarkdac1d172014-06-17 05:15:38 -07002715 if (recType == REC_TYPE_ANGLE) {
2716 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07002717 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07002718 continue;
2719 }
2720 lastAngle = tIndex;
2721 ++angleCount;
2722 bumpStep = true;
2723 }
caryclark624637c2015-05-11 07:21:27 -07002724 if (recType == REC_TYPE_COINCIDENCE) {
2725 ++coinMax;
2726 if (!draw_coincidence || !inStepRange) {
2727 continue;
2728 }
2729 lastCoin = tIndex;
2730 ++coinCount;
2731 bumpStep = true;
2732 }
caryclarkdac1d172014-06-17 05:15:38 -07002733 if (recType == REC_TYPE_SECT) {
2734 if (records.length != 2) {
2735 console.log("expect only two elements: " + records.length);
2736 throw "stop execution";
2737 }
2738 ++sectMax;
2739 var sectBump = 1;
2740 switch (fragType) {
2741 case INTERSECT_LINE:
2742 case INTERSECT_QUAD_LINE:
2743 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002744 case INTERSECT_CONIC_LINE:
2745 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07002746 case INTERSECT_SELF_CUBIC:
2747 case INTERSECT_CUBIC_LINE:
2748 case INTERSECT_CUBIC_QUAD:
2749 case INTERSECT_CUBIC:
2750 sectBump = 1;
2751 break;
2752 case INTERSECT_LINE_2:
2753 case INTERSECT_QUAD_LINE_2:
2754 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07002755 case INTERSECT_CONIC_LINE_2:
2756 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07002757 case INTERSECT_CUBIC_LINE_2:
2758 case INTERSECT_CUBIC_QUAD_2:
2759 case INTERSECT_CUBIC_2:
2760 sectBump = 2;
2761 break;
2762 case INTERSECT_LINE_NO:
2763 case INTERSECT_QUAD_LINE_NO:
2764 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07002765 case INTERSECT_CONIC_LINE_NO:
2766 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07002767 case INTERSECT_SELF_CUBIC_NO:
2768 case INTERSECT_CUBIC_LINE_NO:
2769 case INTERSECT_CUBIC_QUAD_NO:
2770 case INTERSECT_CUBIC_NO:
2771 sectBump = 0;
2772 break;
2773 case INTERSECT_CUBIC_LINE_3:
2774 case INTERSECT_CUBIC_QUAD_3:
2775 case INTERSECT_CUBIC_3:
2776 sectBump = 3;
2777 break;
2778 case INTERSECT_CUBIC_QUAD_4:
2779 case INTERSECT_CUBIC_4:
2780 sectBump = 4;
2781 break;
2782 default:
2783 console.log("missing case " + records.length);
2784 throw "stop execution";
2785 }
2786 sectMax2 += sectBump;
2787 if (draw_intersection <= 1 || !inStepRange) {
2788 continue;
2789 }
2790 lastSect = tIndex;
2791 sectCount += sectBump;
2792 bumpStep = true;
2793 }
2794 if (recType == REC_TYPE_SORT) {
2795 ++sortMax;
2796 if (!draw_sort || !inStepRange) {
2797 continue;
2798 }
2799 lastSort = tIndex;
2800 ++sortCount;
2801 bumpStep = true;
2802 }
caryclark03b03ca2015-04-23 09:13:37 -07002803 if (recType == REC_TYPE_TOP) {
2804 ++topMax;
2805 if (!draw_top || !inStepRange) {
2806 continue;
2807 }
2808 lastTop = tIndex;
2809 ++topCount;
2810 bumpStep = true;
2811 }
caryclarkdac1d172014-06-17 05:15:38 -07002812 if (recType == REC_TYPE_MARK) {
2813 ++markMax;
2814 if (!draw_mark || !inStepRange) {
2815 continue;
2816 }
2817 lastMark = tIndex;
2818 ++markCount;
2819 bumpStep = true;
2820 }
2821 if (bumpStep) {
2822 lastIndex = tIndex;
2823 logStart = test[tIndex + 1];
2824 logRange = records.length / 2;
2825 ++curStep;
2826 }
2827 }
2828 stepMax = (draw_add ? addMax : 0)
2829 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07002830 + (draw_angle ? angleMax : 0)
caryclark624637c2015-05-11 07:21:27 -07002831 + (draw_coincidence ? coinMax : 0)
caryclark54359292015-03-26 07:52:43 -07002832 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002833 + (draw_sort ? sortMax : 0)
caryclark03b03ca2015-04-23 09:13:37 -07002834 + (draw_top ? topMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002835 + (draw_mark ? markMax : 0)
2836 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
2837 if (stepMax == 0) {
caryclark624637c2015-05-11 07:21:27 -07002838 stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax;
caryclarkdac1d172014-06-17 05:15:38 -07002839 }
2840 drawnPts = [];
2841 drawnLines = [];
2842 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07002843 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07002844 drawnCubics = [];
2845 focusXmin = focusYmin = Infinity;
2846 focusXmax = focusYmax = -Infinity;
2847 var pathIndex = 0;
2848 var opLetter = 'S';
2849 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
2850 var recType = test[tIndex];
2851 var records = test[tIndex + 2];
2852 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
2853 var fragType = records[recordIndex];
2854 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
2855 console.log("unknown in range frag type: " + fragType);
2856 throw "stop execution";
2857 }
2858 var frags = records[recordIndex + 1];
2859 focus_enabled = false;
2860 switch (recType) {
2861 case REC_TYPE_COMPUTED:
2862 if (draw_computed == 0) {
2863 continue;
2864 }
2865 ctx.lineWidth = 1;
2866 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
2867 ctx.fillStyle = "blue";
2868 var drawThis = false;
2869 switch (fragType) {
2870 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002871 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
2872 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002873 drawQuad(frags[0], frags[1], frags[2], frags[3],
2874 frags[4], frags[5]);
2875 drawThis = true;
2876 }
2877 break;
caryclark1049f122015-04-20 08:31:59 -07002878 case PATH_CONIC:
2879 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
2880 && (draw_computed & 7) == pathIndex)) {
2881 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2882 frags[4], frags[5], frags[6]);
2883 drawThis = true;
2884 }
2885 break;
caryclarkdac1d172014-06-17 05:15:38 -07002886 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07002887 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
2888 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002889 drawCubic(frags[0], frags[1], frags[2], frags[3],
2890 frags[4], frags[5], frags[6], frags[7]);
2891 drawThis = true;
2892 }
2893 ++pathIndex;
2894 break;
2895 case COMPUTED_SET_1:
2896 pathIndex = 0;
2897 break;
2898 case COMPUTED_SET_2:
2899 pathIndex = 1;
2900 break;
2901 default:
2902 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
2903 throw "stop execution";
2904 }
2905 if (!drawThis || collect_bounds) {
2906 break;
2907 }
2908 drawCurveSpecials(test, frags, fragType);
2909 break;
2910 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07002911 case REC_TYPE_PATH2:
caryclarkdac1d172014-06-17 05:15:38 -07002912 if (!draw_path) {
2913 continue;
2914 }
2915 var firstPath = tIndex < secondPath;
2916 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
2917 continue;
2918 }
2919 ctx.lineWidth = 1;
2920 ctx.strokeStyle = firstPath ? "black" : "red";
2921 ctx.fillStyle = "blue";
caryclark54359292015-03-26 07:52:43 -07002922 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07002923 switch (fragType) {
2924 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07002925 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
2926 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07002927 break;
2928 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07002929 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
2930 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
2931 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07002932 break;
caryclark1049f122015-04-20 08:31:59 -07002933 case PATH_CONIC:
2934 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
2935 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
2936 frags2[4], frags2[5], frags2[6]);
2937 break;
caryclarkdac1d172014-06-17 05:15:38 -07002938 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07002939 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
2940 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
2941 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07002942 break;
2943 default:
caryclark54359292015-03-26 07:52:43 -07002944 console.log("unknown REC_TYPE_PATH2 frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002945 throw "stop execution";
2946 }
2947 if (collect_bounds) {
2948 break;
2949 }
caryclark54359292015-03-26 07:52:43 -07002950 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002951 break;
2952 case REC_TYPE_OP:
2953 switch (fragType) {
2954 case OP_INTERSECT: opLetter = 'I'; break;
2955 case OP_DIFFERENCE: opLetter = 'D'; break;
2956 case OP_UNION: opLetter = 'U'; break;
2957 case OP_XOR: opLetter = 'X'; break;
2958 default:
2959 console.log("unknown REC_TYPE_OP frag type: " + fragType);
2960 throw "stop execution";
2961 }
2962 break;
2963 case REC_TYPE_ACTIVE:
2964 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
2965 continue;
2966 }
2967 var x1 = frags[SPAN_X1];
2968 var y1 = frags[SPAN_Y1];
2969 var x2 = frags[SPAN_X2];
2970 var y2 = frags[SPAN_Y2];
caryclark1049f122015-04-20 08:31:59 -07002971 var x3, y3, x3, y4, t1, t2, w;
caryclarkdac1d172014-06-17 05:15:38 -07002972 ctx.lineWidth = 3;
2973 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2974 focus_enabled = true;
2975 switch (fragType) {
2976 case ACTIVE_LINE_SPAN:
2977 t1 = frags[SPAN_L_T];
2978 t2 = frags[SPAN_L_TEND];
2979 drawLinePartial(x1, y1, x2, y2, t1, t2);
2980 if (draw_id) {
2981 drawLinePartialID(frags[0], x1, y1, x2, y2, t1, t2);
2982 }
2983 break;
2984 case ACTIVE_QUAD_SPAN:
2985 x3 = frags[SPAN_X3];
2986 y3 = frags[SPAN_Y3];
2987 t1 = frags[SPAN_Q_T];
2988 t2 = frags[SPAN_Q_TEND];
2989 drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2990 if (draw_id) {
2991 drawQuadPartialID(frags[0], x1, y1, x2, y2, x3, y3, t1, t2);
2992 }
2993 break;
caryclark1049f122015-04-20 08:31:59 -07002994 case ACTIVE_CONIC_SPAN:
2995 x3 = frags[SPAN_X3];
2996 y3 = frags[SPAN_Y3];
2997 t1 = frags[SPAN_K_T];
2998 t2 = frags[SPAN_K_TEND];
2999 w = frags[SPAN_K_W];
3000 drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
3001 if (draw_id) {
3002 drawConicPartialID(frags[0], x1, y1, x2, y2, x3, y3, w, t1, t2);
3003 }
3004 break;
caryclarkdac1d172014-06-17 05:15:38 -07003005 case ACTIVE_CUBIC_SPAN:
3006 x3 = frags[SPAN_X3];
3007 y3 = frags[SPAN_Y3];
3008 x4 = frags[SPAN_X4];
3009 y4 = frags[SPAN_Y4];
3010 t1 = frags[SPAN_C_T];
3011 t2 = frags[SPAN_C_TEND];
3012 drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
3013 if (draw_id) {
3014 drawCubicPartialID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
3015 }
3016 break;
3017 default:
3018 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
3019 throw "stop execution";
3020 }
3021 break;
3022 case REC_TYPE_ACTIVE_OP:
3023 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
3024 continue;
3025 }
3026 focus_enabled = true;
3027 ctx.lineWidth = 3;
3028 var activeSpan = frags[7] == "1";
3029 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
3030 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3031 drawCurve(curve);
3032 if (draw_op > 1) {
3033 drawArc(curve, false, frags[3], frags[4]);
3034 drawArc(curve, true, frags[5], frags[6]);
3035 }
3036 break;
3037 case REC_TYPE_ADD:
3038 if (!draw_add) {
3039 continue;
3040 }
3041 ctx.lineWidth = 3;
3042 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
3043 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
3044 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
3045 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
3046 : "rgba(127,0,127, 0.3)";
3047 focus_enabled = true;
3048 switch (fragType) {
3049 case ADD_MOVETO:
3050 break;
3051 case ADD_LINETO:
3052 if (step_limit == 0 || tIndex >= lastAdd) {
3053 drawLine(frags[0], frags[1], frags[2], frags[3]);
3054 }
3055 break;
3056 case ADD_QUADTO:
3057 if (step_limit == 0 || tIndex >= lastAdd) {
3058 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
3059 }
3060 break;
caryclark1049f122015-04-20 08:31:59 -07003061 case ADD_CONICTO:
3062 if (step_limit == 0 || tIndex >= lastAdd) {
3063 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3064 frags[4], frags[5], frags[6]);
3065 }
3066 break;
caryclarkdac1d172014-06-17 05:15:38 -07003067 case ADD_CUBICTO:
3068 if (step_limit == 0 || tIndex >= lastAdd) {
3069 drawCubic(frags[0], frags[1], frags[2], frags[3],
3070 frags[4], frags[5], frags[6], frags[7]);
3071 }
3072 break;
3073 case ADD_CLOSE:
3074 ++closeCount;
3075 break;
3076 case ADD_FILL:
3077 break;
3078 default:
3079 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
3080 throw "stop execution";
3081 }
3082 break;
3083 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07003084 angleBetween = frags[18] == "T";
3085 afterIndex = 0;
3086 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07003087 continue;
3088 }
3089 focus_enabled = true;
3090 ctx.lineWidth = 3;
3091 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07003092 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
3093 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
3094 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07003095 drawCurve(leftCurve);
3096 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07003097 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07003098 drawCurve(midCurve);
3099 if (draw_angle > 1) {
3100 drawOrder(leftCurve, 'L');
3101 drawOrder(rightCurve, 'R');
3102 }
3103 break;
caryclark54359292015-03-26 07:52:43 -07003104 case REC_TYPE_AFTERPART:
3105 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
3106 continue;
3107 }
3108 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
3109 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
3110 : "rgba(0,0,255, 1.0)";
3111 switch (fragType) {
3112 case PATH_LINE:
3113 drawLine(frags[0], frags[1], frags[2], frags[3]);
3114 break;
3115 case PATH_QUAD:
3116 drawQuad(frags[0], frags[1], frags[2], frags[3],
3117 frags[4], frags[5]);
3118 break;
caryclark1049f122015-04-20 08:31:59 -07003119 case PATH_CONIC:
3120 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3121 frags[4], frags[5], frags[6]);
3122 break;
caryclark54359292015-03-26 07:52:43 -07003123 case PATH_CUBIC:
3124 drawCubic(frags[0], frags[1], frags[2], frags[3],
caryclark1049f122015-04-20 08:31:59 -07003125 frags[4], frags[5], frags[6], frags[7]);
caryclark54359292015-03-26 07:52:43 -07003126 break;
3127 default:
3128 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
3129 throw "stop execution";
3130 }
3131 ++afterIndex;
3132 break;
caryclark624637c2015-05-11 07:21:27 -07003133 case REC_TYPE_COINCIDENCE:
3134 if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) {
3135 continue;
3136 }
3137 focus_enabled = true;
3138 ctx.lineWidth = 3;
3139 ctx.strokeStyle = "rgba(127,45,63, 0.3)";
3140 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3141 drawCurve(curve);
3142 break;
caryclarkdac1d172014-06-17 05:15:38 -07003143 case REC_TYPE_SECT:
3144 if (!draw_intersection) {
3145 continue;
3146 }
3147 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
3148 continue;
3149 }
3150 // draw_intersection == 1 : show all
3151 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
3152 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
3153 ctx.lineWidth = 1;
3154 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3155 ctx.fillStyle = "blue";
3156 focus_enabled = true;
3157 var f = [];
3158 var c1s;
3159 var c1l;
3160 var c2s;
3161 var c2l;
3162 switch (fragType) {
3163 case INTERSECT_LINE:
3164 f.push(5, 6, 0, 7);
3165 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
3166 break;
3167 case INTERSECT_LINE_2:
3168 f.push(5, 6, 0, 10);
3169 f.push(8, 9, 7, 15);
3170 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
3171 break;
3172 case INTERSECT_LINE_NO:
3173 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
3174 break;
3175 case INTERSECT_QUAD_LINE:
3176 f.push(7, 8, 0, 9);
3177 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
3178 break;
3179 case INTERSECT_QUAD_LINE_2:
3180 f.push(7, 8, 0, 12);
3181 f.push(10, 11, 9, 17);
3182 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
3183 break;
3184 case INTERSECT_QUAD_LINE_NO:
3185 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
3186 break;
3187 case INTERSECT_QUAD:
3188 f.push(7, 8, 0, 9);
3189 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
3190 break;
3191 case INTERSECT_QUAD_2:
3192 f.push(7, 8, 0, 12);
3193 f.push(10, 11, 9, 19);
3194 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
3195 break;
3196 case INTERSECT_QUAD_NO:
3197 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
3198 break;
caryclark1049f122015-04-20 08:31:59 -07003199 case INTERSECT_CONIC_LINE:
3200 f.push(8, 9, 0, 10);
3201 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
3202 break;
3203 case INTERSECT_CONIC_LINE_2:
3204 f.push(8, 9, 0, 12);
3205 f.push(11, 12, 10, 18);
3206 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
3207 break;
3208 case INTERSECT_CONIC_LINE_NO:
3209 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
3210 break;
3211 case INTERSECT_CONIC:
3212 f.push(8, 9, 0, 10);
3213 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
3214 break;
3215 case INTERSECT_CONIC_2:
3216 f.push(8, 9, 0, 13);
3217 f.push(11, 12, 10, 21);
3218 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
3219 break;
3220 case INTERSECT_CONIC_NO:
3221 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
3222 break;
caryclarkdac1d172014-06-17 05:15:38 -07003223 case INTERSECT_SELF_CUBIC:
3224 f.push(9, 10, 0, 11);
3225 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
3226 break;
3227 case INTERSECT_SELF_CUBIC_NO:
3228 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
3229 break;
3230 case INTERSECT_CUBIC_LINE:
3231 f.push(9, 10, 0, 11);
3232 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3233 break;
3234 case INTERSECT_CUBIC_LINE_2:
3235 f.push(9, 10, 0, 14);
3236 f.push(12, 13, 11, 19);
3237 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3238 break;
3239 case INTERSECT_CUBIC_LINE_3:
3240 f.push(9, 10, 0, 17);
3241 f.push(12, 13, 11, 22);
3242 f.push(15, 16, 14, 23);
3243 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3244 break;
3245 case INTERSECT_CUBIC_QUAD_NO:
3246 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3247 break;
3248 case INTERSECT_CUBIC_QUAD:
3249 f.push(9, 10, 0, 11);
3250 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3251 break;
3252 case INTERSECT_CUBIC_QUAD_2:
3253 f.push(9, 10, 0, 14);
3254 f.push(12, 13, 11, 21);
3255 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3256 break;
3257 case INTERSECT_CUBIC_QUAD_3:
3258 f.push(9, 10, 0, 17);
3259 f.push(12, 13, 11, 24);
3260 f.push(15, 16, 14, 25);
3261 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3262 break;
3263 case INTERSECT_CUBIC_QUAD_4:
3264 f.push(9, 10, 0, 20);
3265 f.push(12, 13, 11, 27);
3266 f.push(15, 16, 14, 28);
3267 f.push(18, 19, 17, 29);
3268 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3269 break;
3270 case INTERSECT_CUBIC_LINE_NO:
3271 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3272 break;
3273 case INTERSECT_CUBIC:
3274 f.push(9, 10, 0, 11);
3275 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3276 break;
3277 case INTERSECT_CUBIC_2:
3278 f.push(9, 10, 0, 14);
3279 f.push(12, 13, 11, 23);
3280 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3281 break;
3282 case INTERSECT_CUBIC_3:
3283 f.push(9, 10, 0, 17);
3284 f.push(12, 13, 11, 26);
3285 f.push(15, 16, 14, 27);
3286 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3287 break;
3288 case INTERSECT_CUBIC_4:
3289 f.push(9, 10, 0, 20);
3290 f.push(12, 13, 11, 29);
3291 f.push(15, 16, 14, 30);
3292 f.push(18, 19, 17, 31);
3293 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3294 break;
3295 case INTERSECT_CUBIC_NO:
3296 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3297 break;
3298 default:
3299 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3300 throw "stop execution";
3301 }
3302 if (draw_intersection != 1) {
3303 var id = -1;
3304 var curve;
3305 switch (c1l) {
3306 case 4:
3307 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3308 if (draw_id) {
3309 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3310 id = idByCurve(test, curve, PATH_LINE);
3311 }
3312 break;
3313 case 6:
3314 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3315 frags[c1s + 4], frags[c1s + 5]);
3316 if (draw_id) {
3317 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3318 frags[c1s + 4], frags[c1s + 5]];
3319 id = idByCurve(test, curve, PATH_QUAD);
3320 }
3321 break;
caryclark1049f122015-04-20 08:31:59 -07003322 case 7:
3323 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3324 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3325 if (draw_id) {
3326 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3327 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3328 id = idByCurve(test, curve, PATH_CONIC);
3329 }
3330 break;
caryclarkdac1d172014-06-17 05:15:38 -07003331 case 8:
3332 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3333 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3334 if (draw_id) {
3335 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3336 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3337 id = idByCurve(test, curve, PATH_CUBIC);
3338 }
3339 break;
3340 }
3341 if (id >= 0) {
3342 drawID(curve, id);
3343 }
3344 id = -1;
3345 switch (c2l) {
3346 case 0:
3347 break;
3348 case 4:
3349 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3350 if (draw_id) {
3351 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3352 id = idByCurve(test, curve, PATH_LINE);
3353 }
3354 break;
3355 case 6:
3356 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3357 frags[c2s + 4], frags[c2s + 5]);
3358 if (draw_id) {
3359 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3360 frags[c2s + 4], frags[c2s + 5]];
3361 id = idByCurve(test, curve, PATH_QUAD);
3362 }
3363 break;
caryclark1049f122015-04-20 08:31:59 -07003364 case 7:
3365 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3366 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3367 if (draw_id) {
3368 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3369 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3370 id = idByCurve(test, curve, PATH_CONIC);
3371 }
3372 break;
caryclarkdac1d172014-06-17 05:15:38 -07003373 case 8:
3374 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3375 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3376 if (draw_id) {
3377 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3378 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3379 id = idByCurve(test, curve, PATH_CUBIC);
3380 }
3381 break;
3382 }
3383 if (id >= 0) {
3384 drawID(curve, id);
3385 }
3386 }
3387 if (collect_bounds) {
3388 break;
3389 }
caryclark54359292015-03-26 07:52:43 -07003390 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3391 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003392 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3393 }
3394 }
3395 if (!draw_intersectT) {
3396 break;
3397 }
3398 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003399 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3400 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003401 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3402 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3403 }
3404 }
3405 break;
3406 case REC_TYPE_SORT:
3407 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3408 continue;
3409 }
3410 ctx.lineWidth = 3;
3411 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3412 focus_enabled = true;
3413 switch (fragType) {
3414 case SORT_UNARY:
3415 case SORT_BINARY:
3416 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3417 drawCurve(curve);
3418 break;
3419 default:
3420 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3421 throw "stop execution";
3422 }
3423 break;
caryclark03b03ca2015-04-23 09:13:37 -07003424 case REC_TYPE_TOP:
3425 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
3426 continue;
3427 }
3428 ctx.lineWidth = 3;
3429 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3430 focus_enabled = true;
3431 {
3432 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3433 drawCurve(curve);
3434 var type = PATH_LINE + (curve.length / 2 - 2);
3435 var mid = pointAtT(curve, type, 0.5);
3436 var d = dxy_at_t(curve, type, 0.5);
3437 drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
3438 }
3439 break;
caryclarkdac1d172014-06-17 05:15:38 -07003440 case REC_TYPE_MARK:
3441 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3442 continue;
3443 }
3444 ctx.lineWidth = 3;
3445 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3446 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3447 focus_enabled = true;
3448 switch (fragType) {
3449 case MARK_LINE:
3450 case MARK_DONE_LINE:
3451 case MARK_UNSORTABLE_LINE:
3452 case MARK_SIMPLE_LINE:
3453 case MARK_SIMPLE_DONE_LINE:
3454 case MARK_DONE_UNARY_LINE:
3455 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3456 frags[5], frags[9]);
3457 if (draw_id) {
3458 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3459 frags[5], frags[9]);
3460 }
3461 break;
3462 case MARK_QUAD:
3463 case MARK_DONE_QUAD:
3464 case MARK_UNSORTABLE_QUAD:
3465 case MARK_SIMPLE_QUAD:
3466 case MARK_SIMPLE_DONE_QUAD:
3467 case MARK_DONE_UNARY_QUAD:
3468 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3469 frags[5], frags[6], frags[7], frags[11]);
3470 if (draw_id) {
3471 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3472 frags[5], frags[6], frags[7], frags[11]);
3473 }
3474 break;
3475 case MARK_CUBIC:
3476 case MARK_DONE_CUBIC:
3477 case MARK_UNSORTABLE_CUBIC:
3478 case MARK_SIMPLE_CUBIC:
3479 case MARK_SIMPLE_DONE_CUBIC:
3480 case MARK_DONE_UNARY_CUBIC:
3481 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3482 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3483 if (draw_id) {
3484 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3485 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3486 }
3487 break;
3488 case MARK_ANGLE_LAST:
3489 // FIXME: ignored for now
3490 break;
3491 default:
3492 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3493 throw "stop execution";
3494 }
3495 break;
3496 default:
3497 continue;
3498 }
3499 }
3500 switch (recType) {
3501 case REC_TYPE_SORT:
3502 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3503 break;
3504 }
3505 var angles = []; // use tangent lines to describe arcs
3506 var windFrom = [];
3507 var windTo = [];
3508 var opp = [];
3509 var minXY = Number.MAX_VALUE;
3510 var partial;
3511 focus_enabled = true;
3512 var someUnsortable = false;
3513 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3514 var fragType = records[recordIndex];
3515 var frags = records[recordIndex + 1];
3516 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3517 (fragType == SORT_BINARY && frags[16]);
3518 someUnsortable |= unsortable;
3519 switch (fragType) {
3520 case SORT_UNARY:
3521 case SORT_BINARY:
3522 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3523 break;
3524 default:
3525 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3526 throw "stop execution";
3527 }
3528 var dx = boundsWidth(partial);
3529 var dy = boundsHeight(partial);
3530 minXY = Math.min(minXY, dx * dx + dy * dy);
3531 if (collect_bounds) {
3532 continue;
3533 }
3534 angles.push(tangent(partial));
3535 var from = frags[12];
3536 var to = frags[12];
3537 var sgn = frags[10];
3538 if (sgn < 0) {
3539 from -= frags[11];
3540 } else if (sgn > 0) {
3541 to -= frags[11];
3542 }
3543 windFrom.push(from + (unsortable ? "!" : ""));
3544 windTo.push(to + (unsortable ? "!" : ""));
3545 opp.push(fragType == SORT_BINARY);
3546 if (draw_sort == 1) {
3547 drawOrder(partial, frags[12]);
3548 } else {
3549 drawOrder(partial, (recordIndex / 2) + 1);
3550 }
3551 }
3552 var radius = Math.sqrt(minXY) / 2 * scale;
3553 radius = Math.min(50, radius);
3554 var scaledRadius = radius / scale;
3555 var centerX = partial[0];
3556 var centerY = partial[1];
3557 if (collect_bounds) {
3558 if (focus_enabled) {
3559 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
3560 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
3561 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
3562 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
3563 }
3564 break;
3565 }
3566 break;
3567 default:
3568 break;
3569 }
3570 }
3571 if (collect_bounds) {
3572 return;
3573 }
3574 if (draw_log && logStart >= 0) {
3575 ctx.font = "normal 10px Arial";
3576 ctx.textAlign = "left";
3577 ctx.beginPath();
3578 var top = screenHeight - 20 - (logRange + 2) * 10;
3579 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
3580 ctx.fillStyle = "white";
3581 ctx.fill();
3582 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3583 if (logStart > 0) {
3584 ctx.fillText(lines[logStart - 1], 50, top + 8);
3585 }
3586 ctx.fillStyle = "black";
3587 for (var idx = 0; idx < logRange; ++idx) {
3588 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
3589 }
3590 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3591 if (logStart + logRange < lines.length) {
3592 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
3593 }
3594 }
3595 if (draw_legend) {
3596 var pos = 0;
caryclark624637c2015-05-11 07:21:27 -07003597 var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07003598 // drawBox(pos++, "yellow", "black", opLetter, true, '');
3599 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
3600 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
3601 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
3602 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
caryclark624637c2015-05-11 07:21:27 -07003603 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey);
caryclarkdac1d172014-06-17 05:15:38 -07003604 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
3605 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
caryclark03b03ca2015-04-23 09:13:37 -07003606 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
caryclarkdac1d172014-06-17 05:15:38 -07003607 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
3608 drawBox(pos++, "black", "white",
3609 (new Array('P', 'P1', 'P2', 'P'))[draw_path], draw_path != 0, pathKey);
3610 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
3611 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
3612 draw_computed != 0, computedKey);
3613 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
3614 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
3615 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
3616 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
3617 if (curve_t) {
3618 drawCurveTControl();
3619 }
3620 ctx.font = "normal 20px Arial";
3621 ctx.fillStyle = "rgba(0,0,0, 0.3)";
3622 ctx.textAlign = "right";
3623 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
3624 }
3625 if (draw_hints) {
3626 ctx.font = "normal 10px Arial";
3627 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3628 ctx.textAlign = "right";
3629 var y = 4;
3630 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
3631 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
3632 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
3633 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07003634 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
3635 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
3636 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
3637 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
3638 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
3639 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
3640 }
3641}
3642
3643function drawBox(y, backC, foreC, str, enable, label) {
3644 ctx.beginPath();
3645 ctx.fillStyle = backC;
3646 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
3647 ctx.fill();
3648 ctx.font = "normal 16px Arial";
3649 ctx.fillStyle = foreC;
3650 ctx.textAlign = "center";
3651 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
3652 if (!enable) {
3653 ctx.fillStyle = "rgba(255,255,255, 0.5)";
3654 ctx.fill();
3655 }
3656 if (label != '') {
3657 ctx.font = "normal 9px Arial";
3658 ctx.fillStyle = "black";
3659 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
3660 }
3661}
3662
3663function drawCurveTControl() {
3664 ctx.lineWidth = 2;
3665 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
3666 ctx.beginPath();
3667 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
3668 ctx.stroke();
3669 var ty = 40 + curveT * (screenHeight - 80);
3670 ctx.beginPath();
3671 ctx.moveTo(screenWidth - 80, ty);
3672 ctx.lineTo(screenWidth - 85, ty - 5);
3673 ctx.lineTo(screenWidth - 85, ty + 5);
3674 ctx.lineTo(screenWidth - 80, ty);
3675 ctx.fillStyle = "rgba(0,0,0, 0.6)";
3676 ctx.fill();
3677 var num = curveT.toFixed(decimal_places);
3678 ctx.font = "normal 10px Arial";
3679 ctx.textAlign = "left";
3680 ctx.fillText(num, screenWidth - 78, ty);
3681}
3682
3683function ptInTControl() {
3684 var e = window.event;
3685 var tgt = e.target || e.srcElement;
3686 var left = tgt.offsetLeft;
3687 var top = tgt.offsetTop;
3688 var x = (e.clientX - left);
3689 var y = (e.clientY - top);
3690 if (x < screenWidth - 80 || x > screenWidth - 50) {
3691 return false;
3692 }
3693 if (y < 40 || y > screenHeight - 80) {
3694 return false;
3695 }
3696 curveT = (y - 40) / (screenHeight - 120);
3697 if (curveT < 0 || curveT > 1) {
3698 throw "stop execution";
3699 }
3700 return true;
3701}
3702
3703function drawTop() {
3704 if (tests[testIndex] == null) {
3705 var str = testDivs[testIndex].textContent;
3706 parse_all(str);
3707 var title = testDivs[testIndex].id.toString();
3708 testTitles[testIndex] = title;
3709 }
3710 init(tests[testIndex]);
3711 redraw();
3712}
3713
3714function redraw() {
3715 if (focus_on_selection) {
3716 collect_bounds = true;
3717 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3718 collect_bounds = false;
3719 if (focusXmin < focusXmax && focusYmin < focusYmax) {
3720 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
3721 }
3722 }
3723 ctx.beginPath();
3724 ctx.fillStyle = "white";
3725 ctx.rect(0, 0, screenWidth, screenHeight);
3726 ctx.fill();
3727 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3728}
3729
3730function dumpCurvePartial(test, id, t0, t1) {
3731 var curve = curveByID(test, id);
3732 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
3733 console.log("id=" + id + " " + name + "=" + curveToString(curve)
3734 + " t0=" + t0 + " t1=" + t1
3735 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
3736}
3737
3738function dumpAngleTest(test, id, t0, t1) {
3739 var curve = curveByID(test, id);
3740 console.log(" { {" + curveToString(curve) + "}, "
3741 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
3742}
3743
3744function dumpLogToConsole() {
3745 if (logStart < 0) {
3746 return;
3747 }
3748 var test = tests[testIndex];
3749 var recType = REC_TYPE_UNKNOWN;
3750 var records;
3751 for (var index = 0; index < test.length; index += 3) {
3752 var lastLineNo = test[index + 1];
3753 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
3754 recType = test[index];
3755 records = test[index + 2];
3756 break;
3757 }
3758 }
3759 if (recType == REC_TYPE_UNKNOWN) {
3760 return;
3761 }
3762 var lines = testLines[testIndex];
3763 for (var idx = 0; idx < logRange; ++idx) {
3764 var line = lines[logStart + idx];
3765 console.log(line);
3766 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3767 var fragType = records[recordIndex];
3768 var frags = records[recordIndex + 1];
3769 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07003770 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
3771 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
3772 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
3773 console.log("\nstatic IntersectData intersectDataSet[] = { //");
3774 dumpAngleTest(test, frags[0], frags[4], frags[5]);
3775 dumpAngleTest(test, frags[6], frags[10], frags[11]);
3776 dumpAngleTest(test, frags[12], frags[16], frags[17]);
3777 console.log("}; //");
3778 }
3779 }
3780 }
3781}
3782
3783var activeKey = 'a';
3784var pathKey = 'b';
3785var pathBackKey = 'B';
3786var centerKey = 'c';
caryclark624637c2015-05-11 07:21:27 -07003787var coincidenceKey = 'C';
caryclarkdac1d172014-06-17 05:15:38 -07003788var addKey = 'd';
3789var deriviativesKey = 'f';
3790var angleKey = 'g';
3791var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07003792var intersectionKey = 'i';
3793var intersectionBackKey = 'I';
3794var sequenceKey = 'j';
3795var midpointKey = 'k';
3796var logKey = 'l';
3797var logToConsoleKey = 'L';
3798var markKey = 'm';
3799var sortKey = 'o';
3800var opKey = 'p';
3801var opBackKey = 'P';
3802var computedKey = 'q';
3803var computedBackKey = 'Q';
3804var stepKey = 's';
3805var stepBackKey = 'S';
3806var intersectTKey = 't';
caryclark03b03ca2015-04-23 09:13:37 -07003807var topKey = 'T';
caryclarkdac1d172014-06-17 05:15:38 -07003808var curveTKey = 'u';
3809var controlLinesBackKey = 'V';
3810var controlLinesKey = 'v';
3811var ptsKey = 'x';
3812var xyKey = 'y';
3813var logCurvesKey = 'z';
3814var focusKey = '`';
3815var idKey = '.';
3816var retinaKey = '\\';
3817
3818function doKeyPress(evt) {
3819 var char = String.fromCharCode(evt.charCode);
3820 var focusWasOn = false;
3821 switch (char) {
3822 case '0':
3823 case '1':
3824 case '2':
3825 case '3':
3826 case '4':
3827 case '5':
3828 case '6':
3829 case '7':
3830 case '8':
3831 case '9':
3832 decimal_places = char - '0';
3833 redraw();
3834 break;
3835 case activeKey:
3836 draw_active ^= true;
3837 redraw();
3838 break;
3839 case addKey:
3840 draw_add ^= true;
3841 redraw();
3842 break;
3843 case angleKey:
caryclark54359292015-03-26 07:52:43 -07003844 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07003845 redraw();
3846 break;
3847 case angleBackKey:
3848 draw_angle = (draw_angle + 2) % 3;
3849 redraw();
3850 break;
3851 case centerKey:
3852 setScale(xmin, xmax, ymin, ymax);
3853 redraw();
3854 break;
caryclark624637c2015-05-11 07:21:27 -07003855 case coincidenceKey:
3856 draw_coincidence ^= true;
3857 redraw();
3858 break;
caryclarkdac1d172014-06-17 05:15:38 -07003859 case controlLinesBackKey:
3860 control_lines = (control_lines + 3) % 4;
3861 redraw();
3862 break;
3863 case controlLinesKey:
3864 control_lines = (control_lines + 1) % 4;
3865 redraw();
3866 break;
3867 case computedBackKey:
3868 draw_computed = (draw_computed + 5) % 6;
3869 redraw();
3870 break;
3871 case computedKey:
3872 draw_computed = (draw_computed + 1) % 6;
3873 redraw();
3874 break;
3875 case curveTKey:
3876 curve_t ^= true;
3877 if (curve_t) {
3878 draw_legend = true;
3879 }
3880 redraw();
3881 break;
3882 case deriviativesKey:
3883 draw_deriviatives = (draw_deriviatives + 1) % 3;
3884 redraw();
3885 break;
3886 case focusKey:
3887 focus_on_selection ^= true;
3888 setScale(xmin, xmax, ymin, ymax);
3889 redraw();
3890 break;
caryclarkdac1d172014-06-17 05:15:38 -07003891 case idKey:
3892 draw_id ^= true;
3893 redraw();
3894 break;
3895 case intersectionBackKey:
3896 draw_intersection = (draw_intersection + 3) % 4;
3897 redraw();
3898 break;
3899 case intersectionKey:
3900 draw_intersection = (draw_intersection + 1) % 4;
3901 redraw();
3902 break;
3903 case intersectTKey:
3904 draw_intersectT ^= true;
3905 redraw();
3906 break;
3907 case logCurvesKey:
3908 logCurves(tests[testIndex]);
3909 break;
3910 case logKey:
3911 draw_log ^= true;
3912 redraw();
3913 break;
3914 case logToConsoleKey:
3915 if (draw_log) {
3916 dumpLogToConsole();
3917 }
3918 break;
3919 case markKey:
3920 draw_mark ^= true;
3921 redraw();
3922 break;
3923 case midpointKey:
3924 draw_midpoint ^= true;
3925 redraw();
3926 break;
3927 case opKey:
3928 draw_op = (draw_op + 1) % 3;
3929 redraw();
3930 break;
3931 case opBackKey:
3932 draw_op = (draw_op + 2) % 3;
3933 redraw();
3934 break;
3935 case pathKey:
3936 draw_path = (draw_path + 1) % 4;
3937 redraw();
3938 break;
3939 case pathBackKey:
3940 draw_path = (draw_path + 3) % 4;
3941 redraw();
3942 break;
3943 case ptsKey:
3944 pt_labels = (pt_labels + 1) % 3;
3945 redraw();
3946 break;
3947 case retinaKey:
3948 retina_scale ^= true;
3949 drawTop();
3950 break;
3951 case sequenceKey:
3952 draw_sequence ^= true;
3953 redraw();
3954 break;
3955 case sortKey:
3956 draw_sort = (draw_sort + 1) % 3;
3957 drawTop();
3958 break;
3959 case stepKey:
3960 step_limit++;
3961 if (step_limit > stepMax) {
3962 step_limit = stepMax;
3963 }
3964 redraw();
3965 break;
3966 case stepBackKey:
3967 step_limit--;
3968 if (step_limit < 0) {
3969 step_limit = 0;
3970 }
3971 redraw();
3972 break;
caryclark03b03ca2015-04-23 09:13:37 -07003973 case topKey:
3974 draw_top ^= true;
3975 redraw();
3976 break;
caryclarkdac1d172014-06-17 05:15:38 -07003977 case xyKey:
3978 debug_xy = (debug_xy + 1) % 3;
3979 redraw();
3980 break;
3981 case '-':
3982 focusWasOn = focus_on_selection;
3983 if (focusWasOn) {
3984 focus_on_selection = false;
3985 scale /= 1.2;
3986 } else {
3987 scale /= 2;
3988 calcLeftTop();
3989 }
3990 redraw();
3991 focus_on_selection = focusWasOn;
3992 break;
3993 case '=':
3994 case '+':
3995 focusWasOn = focus_on_selection;
3996 if (focusWasOn) {
3997 focus_on_selection = false;
3998 scale *= 1.2;
3999 } else {
4000 scale *= 2;
4001 calcLeftTop();
4002 }
4003 redraw();
4004 focus_on_selection = focusWasOn;
4005 break;
4006 case '?':
4007 draw_hints ^= true;
4008 if (draw_hints && !draw_legend) {
4009 draw_legend = true;
4010 }
4011 redraw();
4012 break;
4013 case '/':
4014 draw_legend ^= true;
4015 redraw();
4016 break;
4017 }
4018}
4019
4020function doKeyDown(evt) {
4021 var char = evt.keyCode;
4022 var preventDefault = false;
4023 switch (char) {
4024 case 37: // left arrow
4025 if (evt.shiftKey) {
4026 testIndex -= 9;
4027 }
4028 if (--testIndex < 0)
4029 testIndex = tests.length - 1;
4030 drawTop();
4031 preventDefault = true;
4032 break;
4033 case 39: // right arrow
4034 if (evt.shiftKey) {
4035 testIndex += 9;
4036 }
4037 if (++testIndex >= tests.length)
4038 testIndex = 0;
4039 drawTop();
4040 preventDefault = true;
4041 break;
4042 }
4043 if (preventDefault) {
4044 evt.preventDefault();
4045 return false;
4046 }
4047 return true;
4048}
4049
4050(function() {
4051 var hidden = "hidden";
4052
4053 // Standards:
4054 if (hidden in document)
4055 document.addEventListener("visibilitychange", onchange);
4056 else if ((hidden = "mozHidden") in document)
4057 document.addEventListener("mozvisibilitychange", onchange);
4058 else if ((hidden = "webkitHidden") in document)
4059 document.addEventListener("webkitvisibilitychange", onchange);
4060 else if ((hidden = "msHidden") in document)
4061 document.addEventListener("msvisibilitychange", onchange);
4062 // IE 9 and lower:
4063 else if ('onfocusin' in document)
4064 document.onfocusin = document.onfocusout = onchange;
4065 // All others:
4066 else
4067 window.onpageshow = window.onpagehide
4068 = window.onfocus = window.onblur = onchange;
4069
4070 function onchange (evt) {
4071 var v = 'visible', h = 'hidden',
4072 evtMap = {
4073 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
4074 };
4075
4076 evt = evt || window.event;
4077 if (evt.type in evtMap)
4078 document.body.className = evtMap[evt.type];
4079 else
4080 document.body.className = this[hidden] ? "hidden" : "visible";
4081 }
4082})();
4083
4084function calcXY() {
4085 var e = window.event;
4086 var tgt = e.target || e.srcElement;
4087 var left = tgt.offsetLeft;
4088 var top = tgt.offsetTop;
4089 mouseX = (e.clientX - left) / scale + srcLeft;
4090 mouseY = (e.clientY - top) / scale + srcTop;
4091}
4092
4093function calcLeftTop() {
4094 srcLeft = mouseX - screenWidth / 2 / scale;
4095 srcTop = mouseY - screenHeight / 2 / scale;
4096}
4097
4098var disableClick = false;
4099
4100function handleMouseClick() {
4101 if (disableClick) {
4102 return;
4103 }
4104 if (!curve_t || !ptInTControl()) {
4105 calcXY();
4106 calcLeftTop();
4107 }
4108 redraw();
4109// if (!curve_t || !ptInTControl()) {
4110// mouseX = screenWidth / 2 / scale + srcLeft;
4111// mouseY = screenHeight / 2 / scale + srcTop;
4112// }
4113}
4114
4115function handleMouseOver() {
4116 calcXY();
4117 if (debug_xy != 2) {
4118 return;
4119 }
4120 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
4121 ctx.beginPath();
4122 ctx.rect(300,100,num.length * 6,10);
4123 ctx.fillStyle="white";
4124 ctx.fill();
4125 ctx.font = "normal 10px Arial";
4126 ctx.fillStyle="black";
4127 ctx.textAlign = "left";
4128 ctx.fillText(num, 300, 108);
4129}
4130
4131function start() {
4132 for (var i = 0; i < testDivs.length; ++i) {
4133 tests[i] = null;
4134 }
4135 testIndex = 0;
4136 drawTop();
4137 window.addEventListener('keypress', doKeyPress, true);
4138 window.addEventListener('keydown', doKeyDown, true);
4139 window.onresize = function() {
4140 drawTop();
4141 }
4142 /*
4143 window.onpagehide = function() {
4144 disableClick = true;
4145 }
4146 */
4147 window.onpageshow = function () {
4148 disableClick = false;
4149 }
4150}
4151
4152</script>
4153</head>
4154
4155<body onLoad="start();">
4156<canvas id="canvas" width="750" height="500"
4157 onmousemove="handleMouseOver()"
4158 onclick="handleMouseClick()"
4159 ></canvas >
4160</body>
4161</html>