blob: c8afb448d69cf853546ffabb65ac6b47064c6597 [file] [log] [blame]
caryclarkdac1d172014-06-17 05:15:38 -07001<html>
2<head>
Cary Clark5de52332018-08-30 12:58:23 -04003<div height="0" hidden="true">
Cary Clark9d6049a2018-12-21 13:13:10 -05004<div id="bug8380">
Cary Clark5de52332018-08-30 12:58:23 -04005SkDCubic::ComplexBreak
Cary Clark9d6049a2018-12-21 13:13:10 -05006{{{126, 9.396100044250488281}, {125.6320571899414063, 9.295844078063964844}, {125.1227340698242188, 9.337338447570800781}, {124.6031646728515625, 9.379667282104492188}}},
7inflectionsTs[0]=0.999997776 {{{126.1618761931709827, 9.252680507258252973}, {123.04446008475567, 9.506653492188940291}}},
8SkDCubic::ComplexBreak
9{{{124.6031646728515625, 9.379667282104492188}, {124.1427383422851563, 9.417178153991699219}, {123.6742630004882813, 9.45534515380859375}, {123.28900146484375, 9.396100044250488281}}},
10inflectionsTs[0]=4.14921088e-06 {{{125.984438133710114, 9.267135117035042668}, {123.2218797495565639, 9.492200381017113386}}},
11maxCurvature[0]=0.0817322831 {{{125.8735553329735666, 9.277935394706121386}, {123.1067608854740314, 9.499713475347833835}}},
12SkDCubic::ComplexBreak
13{{{126, 9.396200180053710938}, {125.305999755859375, 9.206999778747558594}, {124.1090011596679688, 9.522199630737304688}, {123.28900146484375, 9.396200180053710938}}},
14inflectionsTs[0]=0.530286644 {{{127.5428560571536707, 9.140180090182106198}, {121.6628069847287179, 9.619260454379688241}}},
15maxCurvature[0]=0.568563182 {{{127.4346914043237859, 9.15278490094694952}, {121.5456828946143446, 9.624913158409162506}}},
16seg=1 {{{0, 353.891998f}, {126, 9.39610004f}}}
17seg=2 {{{126, 9.39610004f}, {125.632057f, 9.29584408f}, {125.122734f, 9.33733845f}, {124.603165f, 9.37966728f}}}
18seg=3 {{{124.603165f, 9.37966728f}, {124.142731f, 9.41717815f}, {123.674263f, 9.45534515f}, {123.289001f, 9.39610004f}}}
19seg=4 {{{123.289001f, 9.39610004f}, {118.119003f, 8.07219982f}}}
20seg=5 {{{118.119003f, 8.07219982f}, {8.17210007f, 104.212997f}}}
21seg=6 {{{8.17210007f, 104.212997f}, {0, 259.298737f}}}
22seg=7 {{{0, 259.298737f}, {0, 353.891998f}}}
23op sect
24seg=8 {{{8.17210007f, 104.212997f}, {-5.82350016f, 369.813995f}}}
25seg=9 {{{-5.82350016f, 369.813995f}, {126, 9.39620018f}}}
26seg=10 {{{126, 9.39620018f}, {125.631981f, 9.29586983f}, {125.12252f, 9.3373785f}, {124.602829f, 9.37972069f}}}
27seg=11 {{{124.602829f, 9.37972069f}, {124.142509f, 9.41722488f}, {123.674164f, 9.45538425f}, {123.289001f, 9.39620018f}}}
28seg=12 {{{123.289001f, 9.39620018f}, {118.119003f, 8.07219982f}}}
29seg=13 {{{118.119003f, 8.07219982f}, {8.17210007f, 104.212997f}}}
30debugShowLineIntersection wtTs[0]=1 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{-5.82350016,369.813995}} wnTs[0]=0 {{{-5.82350016,369.813995}, {126,9.39620018}}}
31debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wnTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
32debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{126,9.39620018}} wnTs[0]=1 {{{-5.82350016,369.813995}, {126,9.39620018}}}
33debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{-5.82350016,369.813995}, {126,9.39620018}}}
34debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{123.289001,9.39620018}, {118.119003,8.07219982}}}
35debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
36debugShowCubicIntersection wtTs[0]=1 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{124.602829,9.37972069}} wnTs[0]=0 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}}
37debugShowCubicLineIntersection wtTs[0]=1 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{123.289001,9.39620018}} wnTs[0]=0 {{{123.289001,9.39620018}, {118.119003,8.07219982}}}
38debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
39debugShowLineIntersection no intersect {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{{0,353.891998}, {126,9.39610004}}}
40debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wnTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
41debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wtTs[1]=0.583904956 {{0,259.298737}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}} wnTs[1]=1
42SkOpSegment::addT insert t=0.583904956 segID=8 spanID=27
43debugShowLineIntersection wtTs[0]=0.583904956 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{0,259.298737}} wnTs[0]=0 {{{0,259.298737}, {0,353.891998}}}
44debugShowLineIntersection wtTs[0]=0.0441765002 {{{-5.82350016,369.813995}, {126,9.39620018}}} {{0,353.891998}} wtTs[1]=1 {{126,9.39620018}} wnTs[0]=0 {{{0,353.891998}, {126,9.39610004}}} wnTs[1]=0.999999744
45SkOpSegment::addT insert t=0.0441765002 segID=9 spanID=28
46debugShowCubicLineIntersection no intersect {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{{-5.82350016,369.813995}, {126,9.39620018}}}
47debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
48debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{8.17210007,104.212997}, {0,259.298737}}}
49debugShowLineIntersection wtTs[0]=0.0441765002 {{{-5.82350016,369.813995}, {126,9.39620018}}} {{0,353.891998}} wnTs[0]=1 {{{0,259.298737}, {0,353.891998}}}
50debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{126,9.39620018}} wnTs[0]=1 {{{0,353.891998}, {126,9.39610004}}}
51-1=(0.375,0.5) [-1]
52SkTSect::addForPerp addBounded span=-1 opp=-1
53-1=(0.5,0.625) [-1]
54SkTSect::addForPerp addBounded span=-1 opp=-1
55-1=(0.625,0.75) [-1]
56SkTSect::addForPerp addBounded span=-1 opp=-1
57-1=(0.75,0.8125) [-1]
58SkTSect::addForPerp addBounded span=-1 opp=-1
59-1=(0.8125,0.875) [-1]
60SkTSect::addForPerp addBounded span=-1 opp=-1
61-1=(0.875,0.9375) [-1]
62SkTSect::addForPerp addBounded span=-1 opp=-1
63SkTSect::addForPerp priorSpan=-1 t=0.937702598 opp=-1
64-1=(0.9375,1) []
65SkTSect::addForPerp addBounded span=-1 opp=-1
66debugShowCubicIntersection wtTs[0]=0.307128906 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{125.624687,9.33981037}} wtTs[1]=0.9375 {{124.700119,9.37182617}} wnTs[0]=0.307191 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} wnTs[1]=0.937702598
67SkOpSegment::addT insert t=0.307128906 segID=10 spanID=29
68SkOpSegment::addT insert t=0.307190555 segID=2 spanID=30
69SkOpSegment::addT insert t=0.9375 segID=10 spanID=31
70SkOpSegment::addT insert t=0.937702598 segID=2 spanID=32
71debugShowCubicIntersection no intersect {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}}
72debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{0,353.891998}, {126,9.39610004}}}
73-1=(0.125,0.1875) [-1]
74SkTSect::addForPerp addBounded span=-1 opp=-1
75-1=(0.1875,0.25) [-1]
76SkTSect::addForPerp addBounded span=-1 opp=-1
77-1=(0.25,0.375) [-1]
78SkTSect::addForPerp addBounded span=-1 opp=-1
79-1=(0.375,0.5) [-1]
80SkTSect::addForPerp addBounded span=-1 opp=-1
81-1=(0.5,0.625) [-1]
82SkTSect::addForPerp addBounded span=-1 opp=-1
83-1=(0.625,0.75) [-1]
84SkTSect::addForPerp addBounded span=-1 opp=-1
85debugShowCubicIntersection wtTs[0]=0.0625 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{124.516449,9.38673687}} wtTs[1]=0.625 {{123.752594,9.4268837}} wnTs[0]=0.0627287 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} wnTs[1]=0.625091708
86SkOpSegment::addT insert t=0.0625 segID=11 spanID=33
87SkOpSegment::addT insert t=0.0627286673 segID=3 spanID=34
88SkOpSegment::addT insert t=0.625 segID=11 spanID=35
89SkOpSegment::addT insert t=0.625091708 segID=3 spanID=36
90debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
91debugShowLineIntersection no intersect {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{{0,353.891998}, {126,9.39610004}}}
92debugShowCubicLineIntersection wtTs[0]=0.999978653 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{123.289001,9.39620018}} wnTs[0]=0 {{{123.289001,9.39620018}, {118.119003,8.07219982}}}
93debugShowLineIntersection wtTs[0]=4.65488731e-06 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{123.289001,9.39610004}} wtTs[1]=1 {{118.119003,8.07219982}} wnTs[0]=0 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} wnTs[1]=1
94debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
95debugShowLineIntersection no intersect {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{{0,353.891998}, {126,9.39610004}}}
96debugShowLineIntersection wtTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{118.119003,8.07219982}} wnTs[0]=1 {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
97debugShowLineIntersection wtTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{118.119003,8.07219982}} wtTs[1]=1 {{8.17210007,104.212997}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} wnTs[1]=1
98debugShowLineIntersection wtTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{8.17210007,104.212997}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}}
99debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} {{126,9.39610004}} wnTs[0]=1 {{{0,353.891998}, {126,9.39610004}}}
100debugShowCubicLineIntersection no intersect {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{{0,353.891998}, {126,9.39610004}}}
101debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
102debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
103debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{8.17210007,104.212997}, {0,259.298737}}}
104debugShowLineIntersection wtTs[0]=0 {{{0,353.891998}, {126,9.39610004}}} {{0,353.891998}} wnTs[0]=1 {{{0,259.298737}, {0,353.891998}}}
105debugShowCubicIntersection wtTs[0]=1 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} {{124.603165,9.37966728}} wnTs[0]=0 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}}
106debugShowCubicLineIntersection wtTs[0]=1 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{123.289001,9.39610004}} wnTs[0]=0 {{{123.289001,9.39610004}, {118.119003,8.07219982}}}
107debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}}
108debugShowLineIntersection wtTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{8.17210007,104.212997}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}}
109debugShowLineIntersection wtTs[0]=1 {{{8.17210007,104.212997}, {0,259.298737}}} {{0,259.298737}} wnTs[0]=0 {{{0,259.298737}, {0,353.891998}}}
110----------------x-x--x-x-------------- addExpanded
11100: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
11201: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
11302: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
11403: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
11504: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
11605: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
11706: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
11807: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
11908: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
12009: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
12110: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
12211: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
12312: seg/base=13/25 seg/base=5/9 MarkCoinStart
12413: seg/base=13/26 seg/base=5/10 MarkCoinEnd
12514: seg/base=4/7 seg/base=12/23 MarkCoinStart
12615: seg/base=4/8 seg/base=12/24 MarkCoinEnd
12716: seg/base=11/33 seg/base=3/34 MarkCoinStart
12817: seg/base=11/35 seg/base=3/36 MarkCoinEnd
12918: seg/base=2/30 seg/base=10/29 MarkCoinStart
13019: seg/base=2/32 seg/base=10/31 MarkCoinEnd
13120: seg/base=9/28 seg/base=1/1 MarkCoinStart
13221: seg/base=9/18 seg/base=1/2 MarkCoinEnd
13322: seg/base=8/15 seg/base=6/11 MarkCoinStart
13423: seg/base=8/27 seg/base=6/12 MarkCoinEnd
135SkOpSegment::debugShowActiveSpans id=8 (8.17210007,104.212997 -2.71619996e-07,259.298737) t=0 tEnd=0.583904956 windSum=? windValue=1
136SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=? windValue=1
137SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=? windValue=1
138SkOpSegment::debugShowActiveSpans id=9 (7.26031715e-07,353.891998 126,9.39620018) t=0.0441765002 tEnd=1 windSum=? windValue=1
139SkOpSegment::debugShowActiveSpans id=10 (126,9.39620018 125.886971,9.36538583 125.760599,9.34795095 125.624687,9.33981037) t=0 tEnd=0.307128906 windSum=? windValue=1
140SkOpSegment::debugShowActiveSpans id=10 (125.624687,9.33981037 125.345733,9.32310212 125.026588,9.34554777 124.700119,9.37182617) t=0.307128906 tEnd=0.9375 windSum=? windValue=1
141SkOpSegment::debugShowActiveSpans id=10 (124.700119,9.37182617 124.66775,9.37443162 124.63531,9.3770743 124.602829,9.37972069) t=0.9375 tEnd=1 windSum=? windValue=1
142SkOpSegment::debugShowActiveSpans id=11 (124.602829,9.37972069 124.574059,9.3820647 124.545259,9.38441166 124.516449,9.38673687) t=0 tEnd=0.0625 windSum=? windValue=1
143SkOpSegment::debugShowActiveSpans id=11 (124.516449,9.38673687 124.257155,9.40766372 123.997126,9.42685982 123.752594,9.4268837) t=0.0625 tEnd=0.625 windSum=? windValue=1
144SkOpSegment::debugShowActiveSpans id=11 (123.752594,9.4268837 123.589573,9.42689962 123.433437,9.41839421 123.289001,9.39620018) t=0.625 tEnd=1 windSum=? windValue=1
145SkOpSegment::debugShowActiveSpans id=12 (123.289001,9.39620018 118.119003,8.07219982) t=0 tEnd=1 windSum=? windValue=1
146SkOpSegment::debugShowActiveSpans id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? windValue=1
147SkOpSegment::debugShowActiveSpans id=1 (0,353.891998 126,9.39610004) t=0 tEnd=1 windSum=? windValue=1
148SkOpSegment::debugShowActiveSpans id=2 (126,9.39610004 125.886971,9.36530236 125.760605,9.34788101 125.624695,9.33975124) t=0 tEnd=0.307190555 windSum=? windValue=1
149SkOpSegment::debugShowActiveSpans id=2 (125.624695,9.33975124 125.345738,9.3230648 125.026588,9.34552196 124.700119,9.37180042) t=0.307190555 tEnd=0.937702598 windSum=? windValue=1
150SkOpSegment::debugShowActiveSpans id=2 (124.700119,9.37180042 124.667862,9.37439685 124.635532,9.37703031 124.603165,9.37966728) t=0.937702598 tEnd=1 windSum=? windValue=1
151SkOpSegment::debugShowActiveSpans id=3 (124.603165,9.37966728 124.574282,9.38202029 124.545364,9.3843762 124.516441,9.38671017) t=0 tEnd=0.0627286673 windSum=? windValue=1
152SkOpSegment::debugShowActiveSpans id=3 (124.516441,9.38671017 124.257145,9.40763418 123.997124,9.42681973 123.752594,9.42682648) t=0.0627286673 tEnd=0.625091708 windSum=? windValue=1
153SkOpSegment::debugShowActiveSpans id=3 (123.752594,9.42682648 123.589574,9.42683098 123.433439,9.41831153 123.289001,9.39610004) t=0.625091708 tEnd=1 windSum=? windValue=1
154SkOpSegment::debugShowActiveSpans id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 tEnd=1 windSum=? windValue=1
155SkOpSegment::debugShowActiveSpans id=5 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? windValue=1
156SkOpSegment::debugShowActiveSpans id=6 (8.17210007,104.212997 0,259.298737) t=0 tEnd=1 windSum=? windValue=1
157SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=? windValue=1
158----------------x-x--x-x-------------- move_multiples
15900: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
16001: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
16102: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
16203: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
16304: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
16405: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
16506: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
16607: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
16708: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
16809: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
16910: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
17011: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
17112: seg/base=13/25 seg/base=5/9 MarkCoinStart
17213: seg/base=13/26 seg/base=5/10 MarkCoinEnd
17314: seg/base=4/7 seg/base=12/23 MarkCoinStart
17415: seg/base=4/8 seg/base=12/24 MarkCoinEnd
17516: seg/base=11/33 seg/base=3/34 MarkCoinStart
17617: seg/base=11/35 seg/base=3/36 MarkCoinEnd
17718: seg/base=2/30 seg/base=10/29 MarkCoinStart
17819: seg/base=2/32 seg/base=10/31 MarkCoinEnd
17920: seg/base=9/28 seg/base=1/1 MarkCoinStart
18021: seg/base=9/18 seg/base=1/2 MarkCoinEnd
18122: seg/base=8/15 seg/base=6/11 MarkCoinStart
18223: seg/base=8/27 seg/base=6/12 MarkCoinEnd
183----------------x-x--x-x-------------- move_nearby
18400: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
18501: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
18602: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
18703: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
18804: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
18905: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
19006: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
19107: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
19208: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
19309: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
19410: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
19511: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
19612: seg/base=13/25 seg/base=5/9 MarkCoinStart
19713: seg/base=13/26 seg/base=5/10 MarkCoinEnd
19814: seg/base=4/7 seg/base=12/23 MarkCoinStart
19915: seg/base=4/8 seg/base=12/24 MarkCoinEnd
20016: seg/base=11/33 seg/base=3/34 MarkCoinStart
20117: seg/base=11/35 seg/base=3/36 MarkCoinEnd
20218: seg/base=2/30 seg/base=10/29 MarkCoinStart
20319: seg/base=2/32 seg/base=10/31 MarkCoinEnd
20420: seg/base=9/28 seg/base=1/1 MarkCoinStart
20521: seg/base=9/18 seg/base=1/2 MarkCoinEnd
20622: seg/base=8/15 seg/base=6/11 MarkCoinStart
20723: seg/base=8/27 seg/base=6/12 MarkCoinEnd
208----------------x-x--x-x-------------- correctEnds
20900: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
21001: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
21102: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
21203: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
21304: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
21405: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
21506: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
21607: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
21708: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
21809: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
21910: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
22011: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
22112: seg/base=13/25 seg/base=5/9 MarkCoinStart
22213: seg/base=13/26 seg/base=5/10 MarkCoinEnd
22314: seg/base=4/7 seg/base=12/23 MarkCoinStart
22415: seg/base=4/8 seg/base=12/24 MarkCoinEnd
22516: seg/base=11/33 seg/base=3/34 MarkCoinStart
22617: seg/base=11/35 seg/base=3/36 MarkCoinEnd
22718: seg/base=2/30 seg/base=10/29 MarkCoinStart
22819: seg/base=2/32 seg/base=10/31 MarkCoinEnd
22920: seg/base=9/28 seg/base=1/1 MarkCoinStart
23021: seg/base=9/18 seg/base=1/2 MarkCoinEnd
23122: seg/base=8/15 seg/base=6/11 MarkCoinStart
23223: seg/base=8/27 seg/base=6/12 MarkCoinEnd
233----------------x-x--x-x-------------- addEndMovedSpans
23400: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
23501: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
23602: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
23703: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
23804: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
23905: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
24006: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
24107: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
24208: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
24309: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
24410: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
24511: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
24612: seg/base=13/25 seg/base=5/9 MarkCoinStart
24713: seg/base=13/26 seg/base=5/10 MarkCoinEnd
24814: seg/base=4/7 seg/base=12/23 MarkCoinStart
24915: seg/base=4/8 seg/base=12/24 MarkCoinEnd
25016: seg/base=11/33 seg/base=3/34 MarkCoinStart
25117: seg/base=11/35 seg/base=3/36 MarkCoinEnd
25218: seg/base=2/30 seg/base=10/29 MarkCoinStart
25319: seg/base=2/32 seg/base=10/31 MarkCoinEnd
25420: seg/base=9/28 seg/base=1/1 MarkCoinStart
25521: seg/base=9/18 seg/base=1/2 MarkCoinEnd
25622: seg/base=8/15 seg/base=6/11 MarkCoinStart
25723: seg/base=8/27 seg/base=6/12 MarkCoinEnd
258----------------x-x--x-x-------------- expand
25900: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
26001: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
26102: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
26203: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin
26304: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin
26405: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
26506: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
26607: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
26708: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin
26809: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin
26910: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin
27011: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin
27112: seg/base=13/25 seg/base=5/9 MarkCoinStart
27213: seg/base=13/26 seg/base=5/10 MarkCoinEnd
27314: seg/base=4/7 seg/base=12/23 MarkCoinStart
27415: seg/base=4/8 seg/base=12/24 MarkCoinEnd
27516: seg/base=11/33 seg/base=3/34 MarkCoinStart
27617: seg/base=11/35 seg/base=3/36 MarkCoinEnd
27718: seg/base=2/30 seg/base=10/29 MarkCoinStart
27819: seg/base=2/32 seg/base=10/31 MarkCoinEnd
27920: seg/base=9/28 seg/base=1/1 MarkCoinStart
28021: seg/base=9/18 seg/base=1/2 MarkCoinEnd
28122: seg/base=8/15 seg/base=6/11 MarkCoinStart
28223: seg/base=8/27 seg/base=6/12 MarkCoinEnd
283------------------xx-x-x-------------- addExpanded
28400: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
28501: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
28602: seg/base=13/25 seg/base=5/9 MarkCoinStart
28703: seg/base=13/26 seg/base=5/10 MarkCoinEnd
28804: seg/base=4/7 seg/base=12/23 MarkCoinStart
28905: seg/base=4/8 seg/base=12/24 MarkCoinEnd
29006: seg/base=11/33 seg/base=3/34 MarkCoinStart
29107: seg/base=11/22 seg/base=3/6 MarkCoinEnd
29208: seg/base=3/36 MarkCoinInsert
29309: seg/base=11/35 MarkCoinInsert
29410: seg/base=2/3 seg/base=10/19 MarkCoinStart
29511: seg/base=2/32 seg/base=10/31 MarkCoinEnd
29612: seg/base=10/29 MarkCoinInsert
29713: seg/base=2/30 MarkCoinInsert
29814: seg/base=9/28 seg/base=1/1 MarkCoinStart
29915: seg/base=9/18 seg/base=1/2 MarkCoinEnd
30016: seg/base=8/15 seg/base=6/11 MarkCoinStart
30117: seg/base=8/27 seg/base=6/12 MarkCoinEnd
302------------------xx-x-x-------------- move_multiples
30300: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
30401: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
30502: seg/base=13/25 seg/base=5/9 MarkCoinStart
30603: seg/base=13/26 seg/base=5/10 MarkCoinEnd
30704: seg/base=4/7 seg/base=12/23 MarkCoinStart
30805: seg/base=4/8 seg/base=12/24 MarkCoinEnd
30906: seg/base=11/33 seg/base=3/34 MarkCoinStart
31007: seg/base=11/22 seg/base=3/6 MarkCoinEnd
31108: seg/base=3/36 MarkCoinInsert
31209: seg/base=11/35 MarkCoinInsert
31310: seg/base=2/3 seg/base=10/19 MarkCoinStart
31411: seg/base=2/32 seg/base=10/31 MarkCoinEnd
31512: seg/base=10/29 MarkCoinInsert
31613: seg/base=2/30 MarkCoinInsert
31714: seg/base=9/28 seg/base=1/1 MarkCoinStart
31815: seg/base=9/18 seg/base=1/2 MarkCoinEnd
31916: seg/base=8/15 seg/base=6/11 MarkCoinStart
32017: seg/base=8/27 seg/base=6/12 MarkCoinEnd
321------------------xx-x-x-------------- move_nearby
32200: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
32301: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
32402: seg/base=13/25 seg/base=5/9 MarkCoinStart
32503: seg/base=13/26 seg/base=5/10 MarkCoinEnd
32604: seg/base=4/7 seg/base=12/23 MarkCoinStart
32705: seg/base=4/8 seg/base=12/24 MarkCoinEnd
32806: seg/base=11/33 seg/base=3/34 MarkCoinStart
32907: seg/base=11/22 seg/base=3/6 MarkCoinEnd
33008: seg/base=3/36 MarkCoinInsert
33109: seg/base=11/35 MarkCoinInsert
33210: seg/base=2/3 seg/base=10/19 MarkCoinStart
33311: seg/base=2/32 seg/base=10/31 MarkCoinEnd
33412: seg/base=10/29 MarkCoinInsert
33513: seg/base=2/30 MarkCoinInsert
33614: seg/base=9/28 seg/base=1/1 MarkCoinStart
33715: seg/base=9/18 seg/base=1/2 MarkCoinEnd
33816: seg/base=8/15 seg/base=6/11 MarkCoinStart
33917: seg/base=8/27 seg/base=6/12 MarkCoinEnd
340------------------xx-x-x-------------- addExpanded
34100: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
34201: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
34302: seg/base=13/25 seg/base=5/9 MarkCoinStart
34403: seg/base=13/26 seg/base=5/10 MarkCoinEnd
34504: seg/base=4/7 seg/base=12/23 MarkCoinStart
34605: seg/base=4/8 seg/base=12/24 MarkCoinEnd
34706: seg/base=11/33 seg/base=3/34 MarkCoinStart
34807: seg/base=11/22 seg/base=3/6 MarkCoinEnd
34908: seg/base=3/36 MarkCoinInsert
35009: seg/base=11/35 MarkCoinInsert
35110: seg/base=2/3 seg/base=10/19 MarkCoinStart
35211: seg/base=2/32 seg/base=10/31 MarkCoinEnd
35312: seg/base=10/29 MarkCoinInsert
35413: seg/base=2/30 MarkCoinInsert
35514: seg/base=9/28 seg/base=1/1 MarkCoinStart
35615: seg/base=9/18 seg/base=1/2 MarkCoinEnd
35716: seg/base=8/15 seg/base=6/11 MarkCoinStart
35817: seg/base=8/27 seg/base=6/12 MarkCoinEnd
359------------------xx-x-x-------------- mark
36000: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
36101: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin
36202: seg/base=13/25 seg/base=5/9 MarkCoinStart
36303: seg/base=13/26 seg/base=5/10 MarkCoinEnd
36404: seg/base=4/7 seg/base=12/23 MarkCoinStart
36505: seg/base=4/8 seg/base=12/24 MarkCoinEnd
36606: seg/base=11/33 seg/base=3/34 MarkCoinStart
36707: seg/base=11/22 seg/base=3/6 MarkCoinEnd
36808: seg/base=3/36 MarkCoinInsert
36909: seg/base=11/35 MarkCoinInsert
37010: seg/base=2/3 seg/base=10/19 MarkCoinStart
37111: seg/base=2/32 seg/base=10/31 MarkCoinEnd
37212: seg/base=10/29 MarkCoinInsert
37313: seg/base=2/30 MarkCoinInsert
37414: seg/base=9/28 seg/base=1/1 MarkCoinStart
37515: seg/base=9/18 seg/base=1/2 MarkCoinEnd
37616: seg/base=8/15 seg/base=6/11 MarkCoinStart
37717: seg/base=8/27 seg/base=6/12 MarkCoinEnd
378-------------------------------------- missing_coincidence
379-------------------------------------- expand
380-------------------------------------- expand
381-------------------------------------- apply
382SkOpSegment::markDone id=5 (118.119003,8.07219982 8.17210007,104.212997) t=0 [9] (118.119003,8.07219982) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
383SkOpSegment::markDone id=12 (123.289001,9.39620018 118.119003,8.07219982) t=0 [23] (123.289001,9.39620018) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
384SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0.0627286673 [34] (124.516441,9.38671017) tEnd=0.625091708 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
385SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0.625091708 [36] (123.752594,9.42682648) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
386SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0 [19] (126,9.39620018) tEnd=0.307128906 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
387SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.307128906 [29] (125.624687,9.33981037) tEnd=0.9375 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
388SkOpSegment::markDone id=1 (0,353.891998 126,9.39610004) t=0 [1] (0,353.891998) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
389SkOpSegment::markDone id=6 (8.17210007,104.212997 0,259.298737) t=0 [11] (8.17210007,104.212997) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
390-------------------------------------- findOverlaps
391SkOpSegment::debugShowActiveSpans id=8 (8.17210007,104.212997 -2.71619996e-07,259.298737) t=0 tEnd=0.583904956 windSum=? oppSum=? windValue=1 oppValue=1
392SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=? windValue=1
393SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=? windValue=1
394SkOpSegment::debugShowActiveSpans id=9 (7.26031715e-07,353.891998 126,9.39620018) t=0.0441765002 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
395SkOpSegment::debugShowActiveSpans id=10 (124.700119,9.37182617 124.66775,9.37443162 124.63531,9.3770743 124.602829,9.37972069) t=0.9375 tEnd=1 windSum=? windValue=1
396SkOpSegment::debugShowActiveSpans id=11 (124.602829,9.37972069 124.574059,9.3820647 124.545259,9.38441166 124.516449,9.38673687) t=0 tEnd=0.0625 windSum=? windValue=1
397SkOpSegment::debugShowActiveSpans id=11 (124.516449,9.38673687 124.257155,9.40766372 123.997126,9.42685982 123.752594,9.4268837) t=0.0625 tEnd=0.625 windSum=? oppSum=? windValue=1 oppValue=1
398SkOpSegment::debugShowActiveSpans id=11 (123.752594,9.4268837 123.589573,9.42689962 123.433437,9.41839421 123.289001,9.39620018) t=0.625 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
399SkOpSegment::debugShowActiveSpans id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
400SkOpSegment::debugShowActiveSpans id=2 (126,9.39610004 125.886971,9.36530236 125.760605,9.34788101 125.624695,9.33975124) t=0 tEnd=0.307190555 windSum=? oppSum=? windValue=1 oppValue=1
401SkOpSegment::debugShowActiveSpans id=2 (125.624695,9.33975124 125.345738,9.3230648 125.026588,9.34552196 124.700119,9.37180042) t=0.307190555 tEnd=0.937702598 windSum=? oppSum=? windValue=1 oppValue=1
402SkOpSegment::debugShowActiveSpans id=2 (124.700119,9.37180042 124.667862,9.37439685 124.635532,9.37703031 124.603165,9.37966728) t=0.937702598 tEnd=1 windSum=? windValue=1
403SkOpSegment::debugShowActiveSpans id=3 (124.603165,9.37966728 124.574282,9.38202029 124.545364,9.3843762 124.516441,9.38671017) t=0 tEnd=0.0627286673 windSum=? windValue=1
404SkOpSegment::debugShowActiveSpans id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
405SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=? windValue=1
406-------------------------------------- calc_angles
407SkOpSegment::sortAngles [8] tStart=0 [15]
408SkOpSegment::sortAngles [8] tStart=0.583904956 [27]
409SkOpAngle::after [8/2] 5/5 tStart=0.583904956 tEnd=0 < [7/23] 23/23 tStart=0 tEnd=1 < [8/3] 21/21 tStart=0.583904956 tEnd=1 F 4
410SkOpAngle::afterPart {{{0,259.298737}, {8.17210034,104.212997}}} id=8
411SkOpAngle::afterPart {{{0,259.298737}, {0,353.891998}}} id=7
412SkOpAngle::afterPart {{{0,259.298737}, {-5.82349988,369.813995}}} id=8
413SkOpSegment::sortAngles [9] tStart=0.0441765002 [28]
414SkOpAngle::after [9/4] 21/21 tStart=0.0441765002 tEnd=0 < [7/24] 7/7 tStart=1 tEnd=0 < [9/5] 5/5 tStart=0.0441765002 tEnd=1 F 4
415SkOpAngle::afterPart {{{0,353.891998}, {-5.82350088,369.813995}}} id=9
416SkOpAngle::afterPart {{{0,353.891998}, {0,259.298737}}} id=7
417SkOpAngle::afterPart {{{0,353.891998}, {125.999999,9.39620018}}} id=9
418SkOpSegment::sortAngles [9] tStart=1 [18]
419SkOpSegment::sortAngles [10] tStart=0.9375 [31]
420SkOpAngle::after [10/7] 17/17 tStart=0.9375 tEnd=1 < [2/19] 17/17 tStart=0.937702598 tEnd=1 < [2/18] 1/1 tStart=0.937702598 tEnd=0.307190555 T 12
421SkOpAngle::afterPart {{{124.700119,9.37180042}, {124.66775,9.37440587}, {124.63531,9.37704855}, {124.602829,9.37969494}}} id=10
422SkOpAngle::afterPart {{{124.700119,9.37180042}, {124.667862,9.37439685}, {124.635532,9.37703031}, {124.603165,9.37966728}}} id=2
423SkOpAngle::afterPart {{{124.700119,9.37180042}, {125.026588,9.34552196}, {125.345738,9.3230648}, {125.624695,9.33975124}}} id=2
424SkOpSegment::sortAngles [11] tStart=0.0625 [33]
425SkOpAngle::after [11/8] 1/1 tStart=0.0625 tEnd=0 < [3/20] 1/1 tStart=0.0627286673 tEnd=0 < [11/9] 17/17 tStart=0.0625 tEnd=0.625 T 12
426SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.545252,9.38438496}, {124.574051,9.382038}, {124.602821,9.37969398}}} id=11
427SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.545364,9.3843762}, {124.574282,9.38202029}, {124.603165,9.37966728}}} id=3
428SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.257148,9.40763702}, {123.997118,9.42683311}, {123.752586,9.42685699}}} id=11
429SkOpSegment::sortAngles [11] tStart=0.625 [35]
430SkOpSegment::sortAngles [11] tStart=1 [22]
431SkOpSegment::sortAngles [13] tStart=0 [25]
432SkOpSegment::sortAngles [13] tStart=1 [26]
433SkOpSegment::sortAngles [2] tStart=0 [3]
434SkOpSegment::sortAngles [2] tStart=0.307190555 [30]
435SkOpSegment::sortAngles [2] tStart=0.937702598 [32]
436SkOpSegment::sortAngles [3] tStart=0.0627286673 [34]
437SkOpSegment::sortAngles [4] tStart=0 [7]
438SkOpSegment::sortAngles [4] tStart=1 [8]
439SkOpSegment::sortAngles [7] tStart=0 [13]
440SkOpSegment::sortAngles [7] tStart=1 [14]
441coinSpan - id=13 t=0 tEnd=1
442coinSpan + id=5 t=0 tEnd=1
443coinSpan - id=4 t=0 tEnd=1
444coinSpan + id=12 t=0 tEnd=1
445coinSpan - id=11 t=0.0625 tEnd=1
446coinSpan + id=3 t=0.0627286673 tEnd=1
447coinSpan - id=2 t=0 tEnd=0.937702598
448coinSpan + id=10 t=0 tEnd=0.9375
449coinSpan - id=9 t=0.0441765002 tEnd=1
450coinSpan + id=1 t=0 tEnd=1
451coinSpan - id=8 t=0 tEnd=0.583904956
452coinSpan + id=6 t=0 tEnd=1
453SkOpSpan::sortableTop dir=kLeft seg=8 t=0.291952478 pt=(4.08605003,181.755859)
454SkOpSpan::sortableTop [0] valid=1 operand=1 span=15 ccw=0 seg=8 {{{8.17210007f, 104.212997f}, {-5.82350016f, 369.813995f}}} t=0.291952478 pt=(4.08605003,181.755859) slope=(-13.9956002,265.600998)
455SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
456SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
457SkOpSegment::markWinding id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 [25] (118.119003,8.07219982) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
458SkOpSegment::markWinding id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 [7] (123.289001,9.39610004) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
459SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.625 [35] (123.752594,9.4268837) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
460SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.0625 [33] (124.516449,9.38673687) tEnd=0.625 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
461SkOpSegment::activeOp id=8 t=0.583904956 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=1 suTo=0 result=1
462SkOpSegment::findNextOp simple
463SkOpSegment::markDone id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
464bridgeOp current id=8 from=(-2.71619996e-07,259.298737) to=(8.17210007,104.212997)
465SkOpSegment::findNextOp simple
466SkOpSegment::markDone id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 [25] (118.119003,8.07219982) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
467bridgeOp current id=13 from=(8.17210007,104.212997) to=(118.119003,8.07219982)
468path.moveTo(-2.71619996e-07,259.298737);
469path.lineTo(8.17210007,104.212997);
470SkOpSegment::findNextOp simple
471SkOpSegment::markDone id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 [7] (123.289001,9.39610004) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
472bridgeOp current id=4 from=(118.119003,8.07219982) to=(123.289001,9.39610004)
473path.lineTo(118.119003,8.07219982);
474SkOpSegment::findNextOp simple
475SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.625 [35] (123.752594,9.4268837) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
476bridgeOp current id=11 from=(123.289001,9.39620018) to=(123.752594,9.4268837)
477path.lineTo(123.289001,9.39610004);
478path.cubicTo(123.433441,9.41839409, 123.589569,9.42689991, 123.752594,9.4268837);
479SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0 [21] (124.602829,9.37972069) tEnd=0.0625 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
480SkOpSegment::markWinding id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.9375 [31] (124.700119,9.37182617) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
481SkOpSegment::markAngle last segment=10 span=31 windSum=1
482SkOpSegment::markWinding id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0 [5] (124.603165,9.37966728) tEnd=0.0627286673 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
483SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.937702598 [32] (124.700119,9.37180042) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
484SkOpSegment::markAngle last segment=2 span=32 windSum=1
485SkOpSegment::findNextOp
486SkOpAngle::dumpOne [11/9] next=11/8 sect=17/17 s=0.0625 [33] e=0.625 [35] sgn=-1 windVal=1 windSum=1 oppVal=1 oppSum=1 operand
487SkOpAngle::dumpOne [11/8] next=3/20 sect=1/1 s=0.0625 [33] e=0 [21] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand
488SkOpAngle::dumpOne [3/20] next=11/9 sect=1/1 s=0.0627286673 [34] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0
489SkOpSegment::activeOp id=11 t=0.0625 tEnd=0 op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
490SkOpSegment::findNextOp chase.append segment=10 span=31 windSum=1
491SkOpSegment::activeOp id=3 t=0.0627286673 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
492SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0 [5] (124.603165,9.37966728) tEnd=0.0627286673 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
493SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.937702598 [32] (124.700119,9.37180042) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
494SkOpSegment::findNextOp chase.append segment=2 span=32 windSum=1
495SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.0625 [33] (124.516449,9.38673687) tEnd=0.625 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1
496SkOpSegment::findNextOp from:[11] to:[11] start=-1132576784 end=-1353716568
497bridgeOp current id=11 from=(123.752594,9.4268837) to=(124.516449,9.38673687)
498path.cubicTo(123.997124,9.42685986, 124.257156,9.40766335, 124.516449,9.38673687);
499SkOpSegment::findNextOp simple
500SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0 [21] (124.602829,9.37972069) tEnd=0.0625 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
501bridgeOp current id=11 from=(124.516449,9.38673687) to=(124.602829,9.37972069)
502path.cubicTo(124.545258,9.38441181, 124.574059,9.38206482, 124.602829,9.37972069);
503SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.307190555 [30] (125.624695,9.33975124) tEnd=0.937702598 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
504SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0 [3] (126,9.39610004) tEnd=0.307190555 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
505SkOpSegment::markWinding id=9 (-5.82350016,369.813995 126,9.39620018) t=0.0441765002 [28] (7.26031715e-07,353.891998) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1
506SkOpSegment::markAngle last segment=9 span=28 windSum=-1
507SkOpSegment::findNextOp
508SkOpAngle::dumpOne [10/7] next=2/19 sect=17/17 s=0.9375 [31] e=1 [20] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand
509SkOpAngle::dumpOne [2/19] next=2/18 sect=17/17 s=0.937702598 [32] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
510SkOpAngle::dumpOne [2/18] next=10/7 sect=1/1 s=0.937702598 [32] e=0.307190555 [30] sgn=1 windVal=1 windSum=1 oppVal=1 oppSum=-1
511SkOpSegment::activeOp id=2 t=0.937702598 tEnd=1 op=sect = result=1
512SkOpSegment::activeOp id=2 t=0.937702598 tEnd=0.307190555 op=sect miFrom=0 miTo=1 suFrom=1 suTo=0 result=0
513SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.307190555 [30] (125.624695,9.33975124) tEnd=0.937702598 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=1
514SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0 [3] (126,9.39610004) tEnd=0.307190555 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=1
515SkOpSegment::markDone id=9 (-5.82350016,369.813995 126,9.39620018) t=0.0441765002 [28] (7.26031715e-07,353.891998) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=1
516SkOpSegment::findNextOp chase.append segment=9 span=28 windSum=-1
517SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.9375 [31] (124.700119,9.37182617) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
518SkOpSegment::findNextOp from:[10] to:[2] start=-1132576976 end=-1353719496
519bridgeOp current id=10 from=(124.602829,9.37972069) to=(124.700119,9.37182617)
520path.cubicTo(124.635307,9.37707424, 124.667747,9.37443161, 124.700119,9.37182617);
521SkOpSegment::markWinding id=7 (0,259.298737 0,353.891998) t=0 [13] (0,259.298737) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
522SkOpSegment::markWinding id=9 (-5.82350016,369.813995 126,9.39620018) t=0 [17] (-5.82350016,369.813995) tEnd=0.0441765002 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
523SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0.583904956 [27] (-2.71619996e-07,259.298737) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
524SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
525SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=-1 oppSum=0 windValue=1 oppValue=0
526SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0
527SkOpSegment::activeOp id=7 t=1 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
528SkOpSegment::markDone id=7 (0,259.298737 0,353.891998) t=0 [13] (0,259.298737) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
529bridgeOp chase.append id=7 windSum=1
530SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
531SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=-1 oppSum=0 windValue=1 oppValue=0
532SkOpSegment::activeOp id=8 t=0.583904956 tEnd=1 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
533SkOpSegment::markDone id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0.583904956 [27] (-2.71619996e-07,259.298737) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
534SkOpSegment::markDone id=9 (-5.82350016,369.813995 126,9.39620018) t=0 [17] (-5.82350016,369.813995) tEnd=0.0441765002 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
535</div>
Cary Clark5de52332018-08-30 12:58:23 -0400536
537
538
539 </div>
caryclarkdac1d172014-06-17 05:15:38 -0700540
541<script type="text/javascript">
542
caryclark55888e42016-07-18 10:01:36 -0700543 var testDivs = [
Cary Clark9d6049a2018-12-21 13:13:10 -0500544 bug8380,
caryclark30b9fdd2016-08-31 14:36:29 -0700545 ];
caryclarkdac1d172014-06-17 05:15:38 -0700546
547var decimal_places = 3; // make this 3 to show more precision
548
549var tests = [];
550var testLines = [];
551var testTitles = [];
552var testIndex = 0;
553var ctx;
554
555var xmin, xmax, focusXmin, focusXmax;
556var ymin, ymax, focusYmin, focusYmax;
557var scale;
558var mouseX, mouseY;
559var srcLeft, srcTop;
560var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700561var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700562var curveT = 0;
563
564var pt_labels = 2;
565var collect_bounds = false;
566var control_lines = 0;
567var curve_t = false;
568var debug_xy = 1;
569var focus_enabled = false;
570var focus_on_selection = false;
571var step_limit = 0;
572var draw_active = false;
573var draw_add = false;
574var draw_angle = 0;
caryclark624637c2015-05-11 07:21:27 -0700575var draw_coincidence = false;
caryclarkdac1d172014-06-17 05:15:38 -0700576var draw_deriviatives = 0;
Cary Clarkff114282016-12-14 11:56:16 -0500577var draw_direction = false;
caryclarkdac1d172014-06-17 05:15:38 -0700578var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700579var draw_id = false;
580var draw_intersection = 0;
581var draw_intersectT = false;
582var draw_legend = true;
583var draw_log = false;
584var draw_mark = false;
585var draw_midpoint = false;
586var draw_op = 0;
587var draw_sequence = false;
588var draw_sort = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700589var draw_top = false;
caryclarkdac1d172014-06-17 05:15:38 -0700590var draw_path = 3;
591var draw_computed = 0;
592var retina_scale = !!window.devicePixelRatio;
593
594var activeCount = 0;
595var addCount = 0;
596var angleCount = 0;
caryclark624637c2015-05-11 07:21:27 -0700597var coinCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700598var opCount = 0;
599var sectCount = 0;
600var sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700601var topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700602var markCount = 0;
603var activeMax = 0;
604var addMax = 0;
605var angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -0700606var coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700607var sectMax = 0;
608var sectMax2 = 0;
609var sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700610var topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700611var markMax = 0;
612var opMax = 0;
613var stepMax = 0;
614var lastIndex = 0;
615var hasPath = false;
caryclark26ad22a2015-10-16 09:03:38 -0700616var hasAlignedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -0700617var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700618var angleBetween = false;
619var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700620
621var firstActiveSpan = -1;
622var logStart = -1;
623var logRange = 0;
624
625var SPAN_ID = 0;
626var SPAN_X1 = SPAN_ID + 1;
627var SPAN_Y1 = SPAN_X1 + 1;
628var SPAN_X2 = SPAN_Y1 + 1;
629var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700630
caryclark55888e42016-07-18 10:01:36 -0700631var SPAN_L_TX = SPAN_Y2 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700632var SPAN_L_TY = SPAN_L_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700633var SPAN_L_OTHER = SPAN_L_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700634var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
635var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
636var SPAN_L_SUM = SPAN_L_OTHERI + 1;
637var SPAN_L_VAL = SPAN_L_SUM + 1;
638var SPAN_L_OPP = SPAN_L_VAL + 1;
639
640var SPAN_X3 = SPAN_Y2 + 1;
641var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700642
caryclark55888e42016-07-18 10:01:36 -0700643var SPAN_Q_TX = SPAN_Y3 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700644var SPAN_Q_TY = SPAN_Q_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700645var SPAN_Q_OTHER = SPAN_Q_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700646var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
647var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
648var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
649var SPAN_Q_VAL = SPAN_Q_SUM + 1;
650var SPAN_Q_OPP = SPAN_Q_VAL + 1;
651
caryclark1049f122015-04-20 08:31:59 -0700652var SPAN_K_W = SPAN_Y3 + 1;
caryclark55888e42016-07-18 10:01:36 -0700653var SPAN_K_TX = SPAN_K_W + 1;
caryclark1049f122015-04-20 08:31:59 -0700654var SPAN_K_TY = SPAN_K_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700655var SPAN_K_OTHER = SPAN_K_TY + 1;
caryclark1049f122015-04-20 08:31:59 -0700656var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
657var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
658var SPAN_K_SUM = SPAN_K_OTHERI + 1;
659var SPAN_K_VAL = SPAN_K_SUM + 1;
660var SPAN_K_OPP = SPAN_K_VAL + 1;
661
caryclarkdac1d172014-06-17 05:15:38 -0700662var SPAN_X4 = SPAN_Y3 + 1;
663var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700664
caryclark55888e42016-07-18 10:01:36 -0700665var SPAN_C_TX = SPAN_Y4 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700666var SPAN_C_TY = SPAN_C_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700667var SPAN_C_OTHER = SPAN_C_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700668var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
669var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
670var SPAN_C_SUM = SPAN_C_OTHERI + 1;
671var SPAN_C_VAL = SPAN_C_SUM + 1;
672var SPAN_C_OPP = SPAN_C_VAL + 1;
673
674var ACTIVE_LINE_SPAN = 1;
675var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700676var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
677var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700678
679var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
680var ADD_LINETO = ADD_MOVETO + 1;
681var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700682var ADD_CONICTO = ADD_QUADTO + 1;
683var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700684var ADD_CLOSE = ADD_CUBICTO + 1;
685var ADD_FILL = ADD_CLOSE + 1;
686
687var PATH_LINE = ADD_FILL + 1;
688var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700689var PATH_CONIC = PATH_QUAD + 1;
690var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700691
692var INTERSECT_LINE = PATH_CUBIC + 1;
693var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
694var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
695var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
696var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
697var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
698var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
699var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
700var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700701var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
702var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
703var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
caryclark55888e42016-07-18 10:01:36 -0700704var INTERSECT_CONIC_QUAD = INTERSECT_CONIC_LINE_NO + 1;
705var INTERSECT_CONIC_QUAD_2 = INTERSECT_CONIC_QUAD + 1;
caryclark6c3b9cd2016-09-26 05:36:58 -0700706var INTERSECT_CONIC_QUAD_3 = INTERSECT_CONIC_QUAD_2 + 1;
707var INTERSECT_CONIC_QUAD_4 = INTERSECT_CONIC_QUAD_3 + 1;
708var INTERSECT_CONIC_QUAD_NO = INTERSECT_CONIC_QUAD_4 + 1;
caryclark55888e42016-07-18 10:01:36 -0700709var INTERSECT_CONIC = INTERSECT_CONIC_QUAD_NO + 1;
caryclark1049f122015-04-20 08:31:59 -0700710var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
711var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
712var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700713var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
714var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
715var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
716var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
717var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
718var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
719var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
720var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
721var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
722var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
723var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
724var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
725var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
726var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
727// FIXME: add cubic 5- 9
728var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
729
730var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
731var SORT_BINARY = SORT_UNARY + 1;
732
733var OP_DIFFERENCE = SORT_BINARY + 1;
734var OP_INTERSECT = OP_DIFFERENCE + 1;
735var OP_UNION = OP_INTERSECT + 1;
736var OP_XOR = OP_UNION + 1;
737
738var MARK_LINE = OP_XOR + 1;
739var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700740var MARK_CONIC = MARK_QUAD + 1;
741var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700742var MARK_DONE_LINE = MARK_CUBIC + 1;
743var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700744var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
745var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700746var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
747var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700748var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
749var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700750var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
751var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700752var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
753var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700754var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
755var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700756var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
757var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700758var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
759var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700760var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
761var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700762var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
763
764var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
765var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
766
caryclark624637c2015-05-11 07:21:27 -0700767var ANGLE_AFTER = COMPUTED_SET_2 + 1;
caryclark54359292015-03-26 07:52:43 -0700768var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700769
caryclark54359292015-03-26 07:52:43 -0700770var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700771
caryclark624637c2015-05-11 07:21:27 -0700772var COIN_MAIN_SPAN = ACTIVE_OP + 1;
773var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1;
774
775var FRAG_TYPE_LAST = COIN_OPP_SPAN;
caryclarkdac1d172014-06-17 05:15:38 -0700776
777var REC_TYPE_UNKNOWN = -1;
778var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700779var REC_TYPE_PATH2 = 1;
780var REC_TYPE_SECT = 2;
781var REC_TYPE_ACTIVE = 3;
782var REC_TYPE_ADD = 4;
783var REC_TYPE_SORT = 5;
784var REC_TYPE_OP = 6;
785var REC_TYPE_MARK = 7;
786var REC_TYPE_COMPUTED = 8;
787var REC_TYPE_COIN = 9;
788var REC_TYPE_ANGLE = 10;
789var REC_TYPE_ACTIVE_OP = 11;
790var REC_TYPE_AFTERPART = 12;
caryclark03b03ca2015-04-23 09:13:37 -0700791var REC_TYPE_TOP = 13;
caryclark624637c2015-05-11 07:21:27 -0700792var REC_TYPE_COINCIDENCE = 14;
caryclark26ad22a2015-10-16 09:03:38 -0700793var REC_TYPE_ALIGNED = 15;
794var REC_TYPE_LAST = REC_TYPE_ALIGNED;
caryclarkdac1d172014-06-17 05:15:38 -0700795
796function strs_to_nums(strs) {
797 var result = [];
798 for (var idx = 1; idx < strs.length; ++idx) {
799 var str = strs[idx];
800 var num = parseFloat(str);
801 if (isNaN(num)) {
802 result.push(str);
803 } else {
804 result.push(num);
805 }
806 }
807 return result;
808}
809
810function filter_str_by(id, str, regex, array) {
811 if (regex.test(str)) {
812 var strs = regex.exec(str);
813 var result = strs_to_nums(strs);
814 array.push(id);
815 array.push(result);
816 return true;
817 }
818 return false;
819}
820
821function construct_regexp2(pattern) {
822 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
823 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
824 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700825 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700826 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
827 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
828 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700829 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700830 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
Cary Clark5de52332018-08-30 12:58:23 -0400831 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
832 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)");
833 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700834 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700835 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700836 escape = escape.replace(/NUM/g, "(-?\\d+)");
837 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
838 return new RegExp(escape, 'i');
839}
840
841function construct_regexp2c(pattern) {
842 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
843 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700844 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700845 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700846 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
847 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700848 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700849 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700850 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
Cary Clark5de52332018-08-30 12:58:23 -0400851 escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
852 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)");
853 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700854 escape = escape.replace(/OPER/g, "[a-z]+");
855 escape = escape.replace(/PATH/g, "pathB?");
856 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700857 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700858 escape = escape.replace(/NUM/g, "(-?\\d+)");
859 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
860 return new RegExp(escape, 'i');
861}
862
863function match_regexp(str, lineNo, array, id, pattern) {
864 var regex = construct_regexp2(pattern);
865 if (filter_str_by(id, str, regex, array)) {
866 return true;
867 }
868 regex = construct_regexp2c(pattern);
869 return filter_str_by(id, str, regex, array);
870}
871
872function endsWith(str, suffix) {
873 return str.indexOf(suffix, str.length - suffix.length) !== -1;
874}
875
876function parse_all(test) {
877 var lines = test.match(/[^\r\n]+/g);
878 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
879 var record = [];
880 var recType = REC_TYPE_UNKNOWN;
881 var lastLineNo;
882 var moveX, moveY;
883 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
884 var line = lines[lineNo];
885 if (line.length == 0) {
886 continue;
887 }
888 var opStart = "SkOpSegment::";
889 if (line.lastIndexOf(opStart, 0) === 0) {
890 line = line.substr(opStart.length);
891 }
892 var angleStart = "SkOpAngle::";
893 if (line.lastIndexOf(angleStart, 0) === 0) {
894 line = line.substr(angleStart.length);
895 }
caryclark624637c2015-05-11 07:21:27 -0700896 var coinStart = "SkOpCoincidence::";
897 if (line.lastIndexOf(coinStart, 0) === 0) {
898 line = line.substr(coinStart.length);
899 }
caryclark54359292015-03-26 07:52:43 -0700900 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
caryclark624637c2015-05-11 07:21:27 -0700901 : line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE
caryclark54359292015-03-26 07:52:43 -0700902 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclark55888e42016-07-18 10:01:36 -0700903 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
caryclark54359292015-03-26 07:52:43 -0700904 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700905 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
906 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
907 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
908 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
caryclark26ad22a2015-10-16 09:03:38 -0700909 : line.lastIndexOf("aligned=", 0) === 0 ? REC_TYPE_ALIGNED
caryclarkdac1d172014-06-17 05:15:38 -0700910 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
caryclark03b03ca2015-04-23 09:13:37 -0700911 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
caryclarkdac1d172014-06-17 05:15:38 -0700912 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
913 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
Cary Clark59d5a0e2017-01-23 14:38:52 +0000914 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
caryclarkdac1d172014-06-17 05:15:38 -0700915 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
916 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700917 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700918 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
919 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
920 : REC_TYPE_UNKNOWN;
921 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
922 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
923 if (recType != REC_TYPE_UNKNOWN) {
924 records.push(recType);
925 records.push(lastLineNo);
926 records.push(record);
927 }
928 record = [];
929 recType = type;
930 lastLineNo = lineNo;
931 }
932 var found = false;
933 switch (recType) {
934 case REC_TYPE_ACTIVE:
935 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700936" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700937 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700938" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700939 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700940" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700941 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700942" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark624637c2015-05-11 07:21:27 -0700943 ) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700944" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700945 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700946" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700947 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700948" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700949 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700950" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700951 );
952 break;
953 case REC_TYPE_ACTIVE_OP:
954 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
955" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
956 );
957 break;
958 case REC_TYPE_ADD:
959 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
960 moveX = record[1][0];
961 moveY = record[1][1];
962 found = true;
963 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
964 record[1].unshift(moveY);
965 record[1].unshift(moveX);
966 moveX = record[1][2];
967 moveY = record[1][3];
968 found = true;
969 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
970 record[1].unshift(moveY);
971 record[1].unshift(moveX);
972 moveX = record[1][4];
973 moveY = record[1][5];
974 found = true;
caryclark1049f122015-04-20 08:31:59 -0700975 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
976 record[1].unshift(moveY);
977 record[1].unshift(moveX);
978 moveX = record[1][4];
979 moveY = record[1][5];
980 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700981 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
982 record[1].unshift(moveY);
983 record[1].unshift(moveX);
984 moveX = record[1][6];
985 moveY = record[1][7];
986 found = true;
987 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
988 found = true;
989 } else {
990 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
991 }
992 break;
caryclark54359292015-03-26 07:52:43 -0700993 case REC_TYPE_AFTERPART:
Cary Clarkff114282016-12-14 11:56:16 -0500994 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL id=IDX")
995 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL id=IDX")
996 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL id=IDX")
997 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL id=IDX")
caryclark54359292015-03-26 07:52:43 -0700998 break;
caryclark26ad22a2015-10-16 09:03:38 -0700999 case REC_TYPE_ALIGNED:
1000 found = match_regexp(line, lineNo, record, PATH_LINE, "aligned=IDX LINE_VAL"
1001 ) || match_regexp(line, lineNo, record, PATH_QUAD, "aligned=IDX QUAD_VAL"
1002 ) || match_regexp(line, lineNo, record, PATH_CONIC, "aligned=IDX CONIC_VAL"
1003 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "aligned=IDX CUBIC_VAL"
1004 );
1005 break;
caryclarkdac1d172014-06-17 05:15:38 -07001006 case REC_TYPE_ANGLE:
Cary Clark59d5a0e2017-01-23 14:38:52 +00001007 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
caryclarkdac1d172014-06-17 05:15:38 -07001008"[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");
1009 break;
1010 case REC_TYPE_COIN:
1011 found = true;
1012 break;
caryclark624637c2015-05-11 07:21:27 -07001013 case REC_TYPE_COINCIDENCE:
1014 found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" +
1015" + id=IDX t=T_VAL tEnd=T_VAL"
1016 ) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" +
1017" - id=IDX t=T_VAL tEnd=T_VAL"
1018 );
1019 break;
caryclarkdac1d172014-06-17 05:15:38 -07001020 case REC_TYPE_COMPUTED:
1021 found = line == "computed quadratics given"
1022 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
1023 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
1024 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -07001025 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -07001026 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
1027 );
1028 break;
1029 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001030 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
1031 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -07001032 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -07001033 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
1034 );
1035 break;
1036 case REC_TYPE_PATH2:
1037 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
1038 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -07001039 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -07001040 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -07001041 );
1042 break;
1043 case REC_TYPE_SECT:
1044 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
1045" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1046 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
1047" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1048 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
1049" no intersect LINE_VAL LINE_VAL"
1050 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
1051" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1052 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
1053" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1054 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
1055" no intersect QUAD_VAL LINE_VAL"
1056 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
1057" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1058 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
1059" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
1060 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
1061" no intersect QUAD_VAL QUAD_VAL"
caryclark55888e42016-07-18 10:01:36 -07001062
caryclark1049f122015-04-20 08:31:59 -07001063 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
1064" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1065 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
1066" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1067 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
1068" no intersect CONIC_VAL LINE_VAL"
caryclark55888e42016-07-18 10:01:36 -07001069
1070 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD, "debugShowConicQuadIntersection" +
1071" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1072 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_2, "debugShowConicQuadIntersection" +
1073" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
caryclark6c3b9cd2016-09-26 05:36:58 -07001074 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_3, "debugShowConicQuadIntersection" +
1075" wtTs[0]=T_VAL CONIC_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"
1076 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_4, "debugShowConicQuadIntersection" +
1077" wtTs[0]=T_VAL CONIC_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 QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL"
caryclark55888e42016-07-18 10:01:36 -07001078 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_NO, "debugShowConicQuadIntersection" +
1079" no intersect CONIC_VAL QUAD_VAL"
1080
caryclark1049f122015-04-20 08:31:59 -07001081 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
1082" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
1083 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
1084" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
1085 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
1086" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -07001087 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
1088" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1089 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
1090" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1091 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
1092" 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"
1093 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
1094" no intersect CUBIC_VAL LINE_VAL"
1095 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
1096" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1097 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
1098" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
1099 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
1100" 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"
1101 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
1102" 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"
1103 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
1104" no intersect CUBIC_VAL QUAD_VAL"
1105 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
1106" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
1107 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
1108" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
1109 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
1110" 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"
1111 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
1112" 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"
1113 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
1114" no intersect CUBIC_VAL CUBIC_VAL"
1115 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
1116" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
1117 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
1118" no self intersect CUBIC_VAL"
1119 );
1120 break;
1121 case REC_TYPE_SORT:
1122 var hasDone = / done/.test(line);
1123 var hasUnorderable = / unorderable/.test(line);
1124 var hasSmall = / small/.test(line);
1125 var hasTiny = / tiny/.test(line);
1126 var hasOperand = / operand/.test(line);
1127 var hasStop = / stop/.test(line);
1128 line.replace(/[ a-z]+$/, "");
1129 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
1130" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
1131 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
1132" [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"
1133 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
1134" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
1135 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
1136" [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"
1137 );
1138 if (found) {
1139 record[1].push(hasDone);
1140 record[1].push(hasUnorderable);
1141 record[1].push(hasSmall);
1142 record[1].push(hasTiny);
1143 record[1].push(hasOperand);
1144 record[1].push(hasStop);
1145 }
1146 break;
caryclark03b03ca2015-04-23 09:13:37 -07001147 case REC_TYPE_TOP:
1148 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1149" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1150 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1151" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1152 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1153" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1154 );
1155 break;
caryclarkdac1d172014-06-17 05:15:38 -07001156 case REC_TYPE_MARK:
1157 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001158" 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 -07001159 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001160" 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 -07001161 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
1162" 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 -07001163 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001164" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
1165 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
1166" 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"
1167 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
1168" 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 -07001169 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
1170" 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 -07001171 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
1172" 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 -07001173 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
1174" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
1175 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
1176" 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 -07001177 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
1178" 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 -07001179 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
1180" 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 -07001181 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -07001182" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -07001183 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark55888e42016-07-18 10:01:36 -07001184" last seg=IDX span=IDX"
1185 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1186" last segment=IDX span=IDX windSum=OPT"
1187 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1188" last seg=IDX span=IDX windSum=OPT"
1189 );
caryclarkdac1d172014-06-17 05:15:38 -07001190 break;
1191 case REC_TYPE_OP:
1192 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
1193 || line.lastIndexOf("operator<", 0) === 0) {
1194 found = true;
1195 break;
1196 }
caryclark54359292015-03-26 07:52:43 -07001197 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -07001198 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -07001199 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -07001200 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
1201 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
1202 );
1203 break;
1204 case REC_TYPE_UNKNOWN:
1205 found = true;
1206 break;
1207 }
1208 if (!found) {
1209 console.log(line + " [" + lineNo + "] of type " + type + " not found");
1210 }
1211 }
1212 if (recType != REC_TYPE_UNKNOWN) {
1213 records.push(recType);
1214 records.push(lastLineNo);
1215 records.push(record);
1216 }
1217 if (records.length >= 1) {
1218 tests[testIndex] = records;
1219 testLines[testIndex] = lines;
1220 }
1221}
1222
1223function init(test) {
1224 var canvas = document.getElementById('canvas');
1225 if (!canvas.getContext) return;
1226 ctx = canvas.getContext('2d');
1227 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
1228 var unscaledWidth = window.innerWidth - 20;
1229 var unscaledHeight = window.innerHeight - 20;
1230 screenWidth = unscaledWidth;
1231 screenHeight = unscaledHeight;
1232 canvas.width = unscaledWidth * resScale;
1233 canvas.height = unscaledHeight * resScale;
1234 canvas.style.width = unscaledWidth + 'px';
1235 canvas.style.height = unscaledHeight + 'px';
1236 if (resScale != 1) {
1237 ctx.scale(resScale, resScale);
1238 }
1239 xmin = Infinity;
1240 xmax = -Infinity;
1241 ymin = Infinity;
1242 ymax = -Infinity;
caryclark26ad22a2015-10-16 09:03:38 -07001243 hasPath = hasAlignedPath = hasComputedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -07001244 firstActiveSpan = -1;
1245 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1246 var recType = test[tIndex];
1247 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
1248 console.log("unknown rec type: " + recType);
1249 throw "stop execution";
1250 }
1251 var records = test[tIndex + 2];
1252 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1253 var fragType = records[recordIndex];
1254 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
1255 console.log("unknown in range frag type: " + fragType);
1256 throw "stop execution";
1257 }
1258 var frags = records[recordIndex + 1];
1259 var first = 0;
1260 var last = -1;
1261 var first2 = 0;
1262 var last2 = 0;
1263 switch (recType) {
caryclark26ad22a2015-10-16 09:03:38 -07001264 case REC_TYPE_ALIGNED:
1265 hasAlignedPath = true;
caryclarkdac1d172014-06-17 05:15:38 -07001266 case REC_TYPE_COMPUTED:
1267 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
1268 break;
1269 }
caryclark26ad22a2015-10-16 09:03:38 -07001270 if (REC_TYPE_COMPUTED == recType) {
1271 hasComputedPath = true;
1272 }
caryclarkdac1d172014-06-17 05:15:38 -07001273 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001274 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -07001275 switch (fragType) {
1276 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07001277 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -07001278 break;
caryclark1049f122015-04-20 08:31:59 -07001279 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07001280 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07001281 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -07001282 break;
1283 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07001284 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -07001285 break;
1286 default:
caryclark55888e42016-07-18 10:01:36 -07001287 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
caryclarkdac1d172014-06-17 05:15:38 -07001288 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1289 throw "stop execution";
1290 }
1291 if (recType == REC_TYPE_PATH) {
1292 hasPath = true;
1293 }
1294 break;
caryclark54359292015-03-26 07:52:43 -07001295 case REC_TYPE_PATH2:
1296 first = 1;
1297 switch (fragType) {
1298 case PATH_LINE:
1299 last = 5;
1300 break;
caryclark1049f122015-04-20 08:31:59 -07001301 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001302 case PATH_QUAD:
1303 last = 7;
1304 break;
1305 case PATH_CUBIC:
1306 last = 9;
1307 break;
1308 default:
caryclark55888e42016-07-18 10:01:36 -07001309 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
caryclark54359292015-03-26 07:52:43 -07001310 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1311 throw "stop execution";
1312 }
1313 if (recType == REC_TYPE_PATH2) {
1314 hasPath = true;
1315 }
1316 break;
caryclarkdac1d172014-06-17 05:15:38 -07001317 case REC_TYPE_ACTIVE:
1318 if (firstActiveSpan < 0) {
1319 firstActiveSpan = tIndex;
1320 }
1321 first = 1;
1322 switch (fragType) {
1323 case ACTIVE_LINE_SPAN:
1324 last = 5;
1325 break;
caryclark1049f122015-04-20 08:31:59 -07001326 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -07001327 case ACTIVE_QUAD_SPAN:
1328 last = 7;
1329 break;
1330 case ACTIVE_CUBIC_SPAN:
1331 last = 9;
1332 break;
1333 default:
1334 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1335 throw "stop execution";
1336 }
1337 break;
1338 case REC_TYPE_ADD:
1339 switch (fragType) {
1340 case ADD_MOVETO:
1341 break;
1342 case ADD_LINETO:
1343 last = 4;
1344 break;
caryclark1049f122015-04-20 08:31:59 -07001345 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -07001346 case ADD_QUADTO:
1347 last = 6;
1348 break;
1349 case ADD_CUBICTO:
1350 last = 8;
1351 break;
1352 case ADD_CLOSE:
1353 case ADD_FILL:
1354 break;
1355 default:
1356 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1357 throw "stop execution";
1358 }
1359 break;
caryclark54359292015-03-26 07:52:43 -07001360 case REC_TYPE_AFTERPART:
1361 switch (fragType) {
1362 case PATH_LINE:
1363 last = 4;
1364 break;
caryclark1049f122015-04-20 08:31:59 -07001365 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001366 case PATH_QUAD:
1367 last = 6;
1368 break;
1369 case PATH_CUBIC:
1370 last = 8;
1371 break;
1372 default:
1373 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1374 throw "stop execution";
1375 }
1376 break;
caryclarkdac1d172014-06-17 05:15:38 -07001377 case REC_TYPE_SECT:
1378 switch (fragType) {
1379 case INTERSECT_LINE:
1380 first = 1; last = 5; first2 = 8; last2 = 12;
1381 break;
1382 case INTERSECT_LINE_2:
1383 first = 1; last = 5; first2 = 11; last2 = 15;
1384 break;
1385 case INTERSECT_LINE_NO:
1386 first = 0; last = 4; first2 = 4; last2 = 8;
1387 break;
caryclark1049f122015-04-20 08:31:59 -07001388 case INTERSECT_CONIC_LINE:
1389 first = 1; last = 7; first2 = 11; last2 = 15;
1390 break;
caryclarkdac1d172014-06-17 05:15:38 -07001391 case INTERSECT_QUAD_LINE:
1392 first = 1; last = 7; first2 = 10; last2 = 14;
1393 break;
caryclark1049f122015-04-20 08:31:59 -07001394 case INTERSECT_CONIC_LINE_2:
1395 first = 1; last = 7; first2 = 14; last2 = 18;
1396 break;
caryclarkdac1d172014-06-17 05:15:38 -07001397 case INTERSECT_QUAD_LINE_2:
1398 first = 1; last = 7; first2 = 13; last2 = 17;
1399 break;
caryclark1049f122015-04-20 08:31:59 -07001400 case INTERSECT_CONIC_LINE_NO:
1401 first = 0; last = 6; first2 = 7; last2 = 11;
1402 break;
caryclarkdac1d172014-06-17 05:15:38 -07001403 case INTERSECT_QUAD_LINE_NO:
1404 first = 0; last = 6; first2 = 6; last2 = 10;
1405 break;
caryclark1049f122015-04-20 08:31:59 -07001406 case INTERSECT_CONIC:
1407 first = 1; last = 7; first2 = 11; last2 = 17;
1408 break;
caryclarkdac1d172014-06-17 05:15:38 -07001409 case INTERSECT_QUAD:
1410 first = 1; last = 7; first2 = 10; last2 = 16;
1411 break;
caryclark1049f122015-04-20 08:31:59 -07001412 case INTERSECT_CONIC_2:
1413 first = 1; last = 7; first2 = 14; last2 = 20;
1414 break;
caryclarkdac1d172014-06-17 05:15:38 -07001415 case INTERSECT_QUAD_2:
1416 first = 1; last = 7; first2 = 13; last2 = 19;
1417 break;
caryclark1049f122015-04-20 08:31:59 -07001418 case INTERSECT_CONIC_NO:
1419 first = 0; last = 6; first2 = 7; last2 = 13;
1420 break;
caryclarkdac1d172014-06-17 05:15:38 -07001421 case INTERSECT_QUAD_NO:
1422 first = 0; last = 6; first2 = 6; last2 = 12;
1423 break;
1424 case INTERSECT_SELF_CUBIC:
1425 first = 1; last = 9;
1426 break;
1427 case INTERSECT_SELF_CUBIC_NO:
1428 first = 0; last = 8;
1429 break;
1430 case INTERSECT_CUBIC_LINE:
1431 first = 1; last = 9; first2 = 12; last2 = 16;
1432 break;
1433 case INTERSECT_CUBIC_LINE_2:
1434 first = 1; last = 9; first2 = 15; last2 = 19;
1435 break;
1436 case INTERSECT_CUBIC_LINE_3:
1437 first = 1; last = 9; first2 = 18; last2 = 22;
1438 break;
1439 case INTERSECT_CUBIC_LINE_NO:
1440 first = 0; last = 8; first2 = 8; last2 = 12;
1441 break;
caryclark55888e42016-07-18 10:01:36 -07001442 case INTERSECT_CONIC_QUAD:
1443 first = 1; last = 7; first2 = 11; last2 = 17;
1444 break;
1445 case INTERSECT_CONIC_QUAD_2:
1446 first = 1; last = 7; first2 = 14; last2 = 20;
1447 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07001448 case INTERSECT_CONIC_QUAD_3:
1449 first = 1; last = 7; first2 = 17; last2 = 23;
1450 break;
1451 case INTERSECT_CONIC_QUAD_4:
1452 first = 1; last = 7; first2 = 20; last2 = 26;
1453 break;
caryclark55888e42016-07-18 10:01:36 -07001454 case INTERSECT_CONIC_QUAD_NO:
1455 first = 0; last = 6; first2 = 7; last2 = 13;
1456 break;
caryclarkdac1d172014-06-17 05:15:38 -07001457 case INTERSECT_CUBIC_QUAD:
1458 first = 1; last = 9; first2 = 12; last2 = 18;
1459 break;
1460 case INTERSECT_CUBIC_QUAD_2:
1461 first = 1; last = 9; first2 = 15; last2 = 21;
1462 break;
1463 case INTERSECT_CUBIC_QUAD_3:
1464 first = 1; last = 9; first2 = 18; last2 = 24;
1465 break;
1466 case INTERSECT_CUBIC_QUAD_4:
1467 first = 1; last = 9; first2 = 21; last2 = 27;
1468 break;
1469 case INTERSECT_CUBIC_QUAD_NO:
1470 first = 0; last = 8; first2 = 8; last2 = 14;
1471 break;
1472 case INTERSECT_CUBIC:
1473 first = 1; last = 9; first2 = 12; last2 = 20;
1474 break;
1475 case INTERSECT_CUBIC_2:
1476 first = 1; last = 9; first2 = 15; last2 = 23;
1477 break;
1478 case INTERSECT_CUBIC_3:
1479 first = 1; last = 9; first2 = 18; last2 = 26;
1480 break;
1481 case INTERSECT_CUBIC_4:
1482 first = 1; last = 9; first2 = 21; last2 = 29;
1483 break;
1484 case INTERSECT_CUBIC_NO:
1485 first = 0; last = 8; first2 = 8; last2 = 16;
1486 break;
1487 default:
1488 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1489 throw "stop execution";
1490 }
1491 break;
1492 default:
1493 continue;
1494 }
1495 for (var idx = first; idx < last; idx += 2) {
1496 xmin = Math.min(xmin, frags[idx]);
1497 xmax = Math.max(xmax, frags[idx]);
1498 ymin = Math.min(ymin, frags[idx + 1]);
1499 ymax = Math.max(ymax, frags[idx + 1]);
1500 }
1501 for (var idx = first2; idx < last2; idx += 2) {
1502 xmin = Math.min(xmin, frags[idx]);
1503 xmax = Math.max(xmax, frags[idx]);
1504 ymin = Math.min(ymin, frags[idx + 1]);
1505 ymax = Math.max(ymax, frags[idx + 1]);
1506 }
1507 }
1508 }
1509 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1510 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1511 var recType = test[tIndex];
1512 var records = test[tIndex + 2];
1513 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1514 var fragType = records[recordIndex];
1515 var frags = records[recordIndex + 1];
1516 switch (recType) {
1517 case REC_TYPE_ACTIVE_OP:
1518 if (!draw_op) {
1519 break;
1520 }
1521 {
1522 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1523 curve_extremes(curve, angleBounds);
1524 }
1525 break;
1526 case REC_TYPE_ANGLE:
1527 if (!draw_angle) {
1528 break;
1529 }
caryclark54359292015-03-26 07:52:43 -07001530 {
caryclarkdac1d172014-06-17 05:15:38 -07001531 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1532 curve_extremes(curve, angleBounds);
1533 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1534 curve_extremes(curve, angleBounds);
1535 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1536 }
1537 break;
caryclark624637c2015-05-11 07:21:27 -07001538 case REC_TYPE_COINCIDENCE:
1539 if (!draw_coincidence) {
1540 break;
1541 }
1542 {
1543 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1544 curve_extremes(curve, angleBounds);
1545 }
1546 break;
caryclarkdac1d172014-06-17 05:15:38 -07001547 case REC_TYPE_SORT:
1548 if (!draw_sort) {
1549 break;
1550 }
1551 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1552 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1553 curve_extremes(curve, angleBounds);
1554 }
1555 break;
caryclark03b03ca2015-04-23 09:13:37 -07001556 case REC_TYPE_TOP:
1557 if (!draw_top) {
1558 break;
1559 }
1560 {
1561 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1562 curve_extremes(curve, angleBounds);
1563 }
1564 break;
caryclarkdac1d172014-06-17 05:15:38 -07001565 }
1566 }
1567 }
1568 xmin = Math.min(xmin, angleBounds[0]);
1569 ymin = Math.min(ymin, angleBounds[1]);
1570 xmax = Math.max(xmax, angleBounds[2]);
1571 ymax = Math.max(ymax, angleBounds[3]);
1572 setScale(xmin, xmax, ymin, ymax);
1573 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001574 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001575 }
1576 if (hasPath == true && hasComputedPath == false && draw_computed) {
1577 draw_computed = 0;
1578 }
1579}
1580
caryclark26ad22a2015-10-16 09:03:38 -07001581function curveByIDMatch(test, id, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001582 var tIndex = -3;
1583 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001584 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001585 if (recType == REC_TYPE_OP) {
1586 continue;
1587 }
caryclark26ad22a2015-10-16 09:03:38 -07001588 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001589 return [];
1590 }
1591 var records = test[tIndex + 2];
1592 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1593 var fragType = records[recordIndex];
1594 var frags = records[recordIndex + 1];
1595 if (frags[0] == id) {
1596 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001597 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001598 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001599 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001600 return [frags[1], frags[2], frags[3], frags[4],
1601 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001602 case PATH_CONIC:
1603 return [frags[1], frags[2], frags[3], frags[4],
1604 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001605 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001606 return [frags[1], frags[2], frags[3], frags[4],
1607 frags[5], frags[6], frags[7], frags[8]];
1608 }
1609 }
1610 }
caryclarkdac1d172014-06-17 05:15:38 -07001611 }
1612 return [];
1613}
1614
caryclark26ad22a2015-10-16 09:03:38 -07001615function curveByID(test, id) {
1616 var result = draw_path >= 4 ? curveByIDMatch(test, id, REC_TYPE_ALIGNED) : [];
1617 if (!result.length) {
1618 result = curveByIDMatch(test, id, REC_TYPE_PATH);
1619 }
1620 return result;
1621}
1622
1623function curvePartialByIDMatch(test, id, t0, t1, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001624 var tIndex = -3;
1625 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001626 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001627 if (recType == REC_TYPE_OP) {
1628 continue;
1629 }
caryclark26ad22a2015-10-16 09:03:38 -07001630 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001631 return [];
1632 }
1633 var records = test[tIndex + 2];
1634 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1635 var fragType = records[recordIndex];
1636 var frags = records[recordIndex + 1];
1637 if (frags[0] == id) {
1638 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001639 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001640 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001641 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001642 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1643 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001644 case PATH_CONIC:
1645 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1646 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001647 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001648 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1649 frags[5], frags[6], frags[7], frags[8], t0, t1);
1650 }
1651 }
1652 }
caryclarkdac1d172014-06-17 05:15:38 -07001653 }
1654 return [];
1655}
1656
caryclark26ad22a2015-10-16 09:03:38 -07001657function curvePartialByID(test, id, t0, t1) {
1658 var result = draw_path >= 4 ? curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_ALIGNED) : [];
1659 if (!result.length) {
1660 result = curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_PATH);
1661 }
1662 return result;
1663}
1664
1665function idByCurveIDMatch(test, frag, type, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001666 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001667 while (tIndex < test.length) {
1668 var recType = test[tIndex];
caryclark26ad22a2015-10-16 09:03:38 -07001669 if (recType != recMatch) {
caryclark54359292015-03-26 07:52:43 -07001670 ++tIndex;
1671 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001672 }
1673 var records = test[tIndex + 2];
1674 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1675 var fragType = records[recordIndex];
1676 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001677 if (frag.length != frags.length - 1) {
1678 continue;
1679 }
caryclarkdac1d172014-06-17 05:15:38 -07001680 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001681 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001682 if (frag[0] != frags[1] || frag[1] != frags[2]
1683 || frag[2] != frags[3] || frag[3] != frags[4]) {
1684 continue;
1685 }
1686 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001687 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001688 if (frag[0] != frags[1] || frag[1] != frags[2]
1689 || frag[2] != frags[3] || frag[3] != frags[4]
1690 || frag[4] != frags[5] || frag[5] != frags[6]) {
1691 continue;
1692 }
1693 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001694 case PATH_CONIC:
1695 if (frag[0] != frags[1] || frag[1] != frags[2]
1696 || frag[2] != frags[3] || frag[3] != frags[4]
1697 || frag[4] != frags[5] || frag[5] != frags[6]
1698 || frag[6] != frags[7]) {
1699 continue;
1700 }
1701 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001702 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001703 if (frag[0] != frags[1] || frag[1] != frags[2]
1704 || frag[2] != frags[3] || frag[3] != frags[4]
1705 || frag[4] != frags[5] || frag[5] != frags[6]
1706 || frag[6] != frags[7] || frag[7] != frags[8]) {
1707 continue;
1708 }
1709 return frags[0];
1710 }
1711 }
1712 ++tIndex;
1713 }
1714 return -1;
1715}
1716
caryclark26ad22a2015-10-16 09:03:38 -07001717function idByCurve(test, frag, type) {
1718 var result = draw_path >= 4 ? idByCurveIDMatch(test, frag, type, REC_TYPE_ALIGNED) : [];
1719 if (!result.length) {
1720 result = idByCurveIDMatch(test, frag, type, REC_TYPE_PATH);
1721 }
1722 return result;
1723}
1724
caryclarkdac1d172014-06-17 05:15:38 -07001725function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001726 var length = curve.length == 7 ? 6 : curve.length;
caryclarked0935a2015-10-22 07:23:52 -07001727 for (var index = 0; index < length; index += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001728 var x = curve[index];
1729 var y = curve[index + 1];
1730 bounds[0] = Math.min(bounds[0], x);
1731 bounds[1] = Math.min(bounds[1], y);
1732 bounds[2] = Math.max(bounds[2], x);
1733 bounds[3] = Math.max(bounds[3], y);
1734 }
1735}
1736
1737function setScale(x0, x1, y0, y1) {
1738 var srcWidth = x1 - x0;
1739 var srcHeight = y1 - y0;
1740 var usableWidth = screenWidth;
1741 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1742 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1743 usableWidth -= (xDigits + yDigits) * 10;
1744 usableWidth -= decimal_places * 10;
1745 if (draw_legend) {
1746 usableWidth -= 40;
1747 }
1748 var hscale = usableWidth / srcWidth;
1749 var vscale = screenHeight / srcHeight;
1750 scale = Math.min(hscale, vscale);
1751 var invScale = 1 / scale;
1752 var sxmin = x0 - invScale * 5;
1753 var symin = y0 - invScale * 10;
1754 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1755 var symax = y1 + invScale * 10;
1756 srcWidth = sxmax - sxmin;
1757 srcHeight = symax - symin;
1758 hscale = usableWidth / srcWidth;
1759 vscale = screenHeight / srcHeight;
1760 scale = Math.min(hscale, vscale);
1761 srcLeft = sxmin;
1762 srcTop = symin;
1763}
1764
1765function drawArc(curve, op, from, to) {
1766 var type = PATH_LINE + (curve.length / 2 - 2);
1767 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1768 var dy = pt.y - curve[1];
1769 var dx = pt.x - curve[0];
1770 var dist = Math.sqrt(dy * dy + dx * dx);
1771 var _dist = dist * scale;
1772 var angle = Math.atan2(dy, dx);
1773 var _px = (curve[0] - srcLeft) * scale;
1774 var _py = (curve[1] - srcTop) * scale;
1775 var divisor = 4;
1776 var endDist;
1777 do {
1778 var ends = [];
1779 for (var index = -1; index <= 1; index += 2) {
1780 var px = Math.cos(index * Math.PI / divisor);
1781 var py = Math.sin(index * Math.PI / divisor);
1782 ends.push(px);
1783 ends.push(py);
1784 }
1785 var endDx = (ends[2] - ends[0]) * scale * dist;
1786 var endDy = (ends[3] - ends[1]) * scale * dist;
1787 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1788 if (endDist < 100) {
1789 break;
1790 }
1791 divisor *= 2;
1792 } while (true);
1793 if (endDist < 30) {
1794 return;
1795 }
1796 if (op) {
1797 divisor *= 2;
1798 }
1799 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1800 ctx.beginPath();
1801 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1802 ctx.stroke();
1803 var saveAlign = ctx.textAlign;
1804 var saveStyle = ctx.fillStyle;
1805 var saveFont = ctx.font;
1806 ctx.textAlign = "center";
1807 ctx.fillStyle = "black";
1808 ctx.font = "normal 24px Arial";
1809 divisor *= 0.8;
1810 for (var index = -1; index <= 1; index += 2) {
1811 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1812 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1813 var _px = (px - srcLeft) * scale;
1814 var _py = (py - srcTop) * scale;
1815 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1816 }
1817 ctx.textAlign = saveAlign;
1818 ctx.fillStyle = saveStyle;
1819 ctx.font = saveFont;
1820}
1821
1822function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001823 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1824 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001825 var x = drawnPts[pts];
1826 var y = drawnPts[pts + 1];
1827 if (px == x && py == y) {
1828 return;
1829 }
1830 }
1831 drawnPts.push(px);
1832 drawnPts.push(py);
1833 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1834 var _px = (px - srcLeft) * scale;
1835 var _py = (py - srcTop) * scale;
1836 ctx.beginPath();
1837 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1838 ctx.closePath();
1839 if (end) {
1840 ctx.fill();
1841 } else {
1842 ctx.stroke();
1843 }
1844 if (debug_xy) {
1845 ctx.textAlign = "left";
1846 ctx.fillText(label, _px + 5, _py);
1847 }
1848}
1849
caryclark1049f122015-04-20 08:31:59 -07001850function coordCount(curveType) {
1851 switch (curveType) {
1852 case PATH_LINE:
1853 return 4;
1854 case PATH_QUAD:
1855 return 6;
1856 case PATH_CONIC:
1857 return 6;
1858 case PATH_CUBIC:
1859 return 8;
1860 }
1861 return -1;
1862}
1863
caryclarkdac1d172014-06-17 05:15:38 -07001864function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001865 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001866 for (var idx = 0; idx < count; idx += 2) {
1867 if (!drawControls && idx != 0 && idx != count - 2) {
1868 continue;
1869 }
1870 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1871 }
1872}
1873
1874function drawControlLines(curve, curveType, drawEnd) {
1875 if (curveType == PATH_LINE) {
1876 return;
1877 }
1878 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1879 drawLine(curve[0], curve[1], curve[2], curve[3]);
1880 drawLine(curve[2], curve[3], curve[4], curve[5]);
1881 if (curveType == PATH_CUBIC) {
1882 drawLine(curve[4], curve[5], curve[6], curve[7]);
1883 if (drawEnd > 1) {
1884 drawLine(curve[6], curve[7], curve[0], curve[1]);
1885 if (drawEnd > 2) {
1886 drawLine(curve[0], curve[1], curve[4], curve[5]);
1887 drawLine(curve[6], curve[7], curve[2], curve[3]);
1888 }
1889 }
1890 } else if (drawEnd > 1) {
1891 drawLine(curve[4], curve[5], curve[0], curve[1]);
1892 }
1893}
1894
1895function pointAtT(curve, curveType, t) {
1896 var xy = {};
1897 switch (curveType) {
1898 case PATH_LINE:
1899 var a = 1 - t;
1900 var b = t;
1901 xy.x = a * curve[0] + b * curve[2];
1902 xy.y = a * curve[1] + b * curve[3];
1903 break;
1904 case PATH_QUAD:
1905 var one_t = 1 - t;
1906 var a = one_t * one_t;
1907 var b = 2 * one_t * t;
1908 var c = t * t;
1909 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1910 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1911 break;
caryclark1049f122015-04-20 08:31:59 -07001912 case PATH_CONIC:
1913 var one_t = 1 - t;
1914 var a = one_t * one_t;
1915 var b = 2 * one_t * t;
1916 var c = t * t;
1917 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1918 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1919 var d = a + b * curve[6] + c;
1920 xy.x /= d;
1921 xy.y /= d;
1922 break;
caryclarkdac1d172014-06-17 05:15:38 -07001923 case PATH_CUBIC:
1924 var one_t = 1 - t;
1925 var one_t2 = one_t * one_t;
1926 var a = one_t2 * one_t;
1927 var b = 3 * one_t2 * t;
1928 var t2 = t * t;
1929 var c = 3 * one_t * t2;
1930 var d = t2 * t;
1931 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1932 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1933 break;
1934 }
1935 return xy;
1936}
caryclark55888e42016-07-18 10:01:36 -07001937
caryclarkdac1d172014-06-17 05:15:38 -07001938function drawPointAtT(curve, curveType) {
1939 var x, y;
1940 var xy = pointAtT(curve, curveType, curveT);
1941 drawPoint(xy.x, xy.y, true);
1942 if (!draw_intersectT) {
1943 return;
1944 }
1945 ctx.fillStyle = "red";
1946 drawTAtPointUp(xy.x, xy.y, curveT);
1947}
1948
1949function drawTAtPointUp(px, py, t) {
1950 var label = t.toFixed(decimal_places);
1951 var _px = (px - srcLeft)* scale;
1952 var _py = (py - srcTop) * scale;
1953 ctx.fillText(label, _px + 5, _py - 10);
1954}
1955
1956function drawTAtPointDown(px, py, t) {
1957 var label = t.toFixed(decimal_places);
1958 var _px = (px - srcLeft)* scale;
1959 var _py = (py - srcTop) * scale;
1960 ctx.fillText(label, _px + 5, _py + 10);
1961}
1962
1963function alreadyDrawnLine(x1, y1, x2, y2) {
1964 if (collect_bounds) {
1965 if (focus_enabled) {
1966 focusXmin = Math.min(focusXmin, x1, x2);
1967 focusYmin = Math.min(focusYmin, y1, y2);
1968 focusXmax = Math.max(focusXmax, x1, x2);
1969 focusYmax = Math.max(focusYmax, y1, y2);
1970 }
1971 return true;
1972 }
1973 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1974 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1975 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1976 return true;
1977 }
1978 }
1979 drawnLines.push(x1);
1980 drawnLines.push(y1);
1981 drawnLines.push(x2);
1982 drawnLines.push(y2);
1983 return false;
1984}
1985
1986function drawLine(x1, y1, x2, y2) {
1987 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1988 return;
1989 }
1990 ctx.beginPath();
1991 ctx.moveTo((x1 - srcLeft) * scale,
1992 (y1 - srcTop) * scale);
1993 ctx.lineTo((x2 - srcLeft) * scale,
1994 (y2 - srcTop) * scale);
1995 ctx.stroke();
1996}
1997
1998function linePartial(x1, y1, x2, y2, t1, t2) {
1999 var dx = x1 - x2;
2000 var dy = y1 - y2;
2001 var array = [
2002 x1 - t1 * dx,
2003 y1 - t1 * dy,
2004 x1 - t2 * dx,
2005 y1 - t2 * dy
2006 ];
2007 return array;
2008}
2009
2010function drawLinePartial(x1, y1, x2, y2, t1, t2) {
2011 var a = linePartial(x1, y1, x2, y2, t1, t2);
2012 var ax = a[0];
2013 var ay = a[1];
2014 var bx = a[2];
2015 var by = a[3];
2016 if (alreadyDrawnLine(ax, ay, bx, by)) {
2017 return;
2018 }
2019 ctx.beginPath();
2020 ctx.moveTo((ax - srcLeft) * scale,
2021 (ay - srcTop) * scale);
2022 ctx.lineTo((bx - srcLeft) * scale,
2023 (by - srcTop) * scale);
2024 ctx.stroke();
2025}
2026
2027function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
2028 if (collect_bounds) {
2029 if (focus_enabled) {
2030 focusXmin = Math.min(focusXmin, x1, x2, x3);
2031 focusYmin = Math.min(focusYmin, y1, y2, y3);
2032 focusXmax = Math.max(focusXmax, x1, x2, x3);
2033 focusYmax = Math.max(focusYmax, y1, y2, y3);
2034 }
2035 return true;
2036 }
2037 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
2038 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
2039 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
2040 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
2041 return true;
2042 }
2043 }
2044 drawnQuads.push(x1);
2045 drawnQuads.push(y1);
2046 drawnQuads.push(x2);
2047 drawnQuads.push(y2);
2048 drawnQuads.push(x3);
2049 drawnQuads.push(y3);
2050 return false;
2051}
2052
2053function drawQuad(x1, y1, x2, y2, x3, y3) {
2054 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
2055 return;
2056 }
2057 ctx.beginPath();
2058 ctx.moveTo((x1 - srcLeft) * scale,
2059 (y1 - srcTop) * scale);
2060 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
2061 (y2 - srcTop) * scale,
2062 (x3 - srcLeft) * scale,
2063 (y3 - srcTop) * scale);
2064 ctx.stroke();
2065}
2066
2067function interp(A, B, t) {
2068 return A + (B - A) * t;
2069}
2070
2071function interp_quad_coords(x1, x2, x3, t)
2072{
2073 var ab = interp(x1, x2, t);
2074 var bc = interp(x2, x3, t);
2075 var abc = interp(ab, bc, t);
2076 return abc;
2077}
2078
2079function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
2080 var ax = interp_quad_coords(x1, x2, x3, t1);
2081 var ay = interp_quad_coords(y1, y2, y3, t1);
2082 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
2083 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
2084 var cx = interp_quad_coords(x1, x2, x3, t2);
2085 var cy = interp_quad_coords(y1, y2, y3, t2);
2086 var bx = 2*dx - (ax + cx)/2;
2087 var by = 2*dy - (ay + cy)/2;
2088 var array = [
2089 ax, ay, bx, by, cx, cy
2090 ];
2091 return array;
2092}
2093
2094function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
2095 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2096 var ax = a[0];
2097 var ay = a[1];
2098 var bx = a[2];
2099 var by = a[3];
2100 var cx = a[4];
2101 var cy = a[5];
2102 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
2103 return;
2104 }
2105 ctx.beginPath();
2106 ctx.moveTo((ax - srcLeft) * scale,
2107 (ay - srcTop) * scale);
2108 ctx.quadraticCurveTo((bx - srcLeft) * scale,
2109 (by - srcTop) * scale,
2110 (cx - srcLeft) * scale,
2111 (cy - srcTop) * scale);
2112 ctx.stroke();
2113}
2114
caryclark1049f122015-04-20 08:31:59 -07002115function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
2116 if (collect_bounds) {
2117 if (focus_enabled) {
2118 focusXmin = Math.min(focusXmin, x1, x2, x3);
2119 focusYmin = Math.min(focusYmin, y1, y2, y3);
2120 focusXmax = Math.max(focusXmax, x1, x2, x3);
2121 focusYmax = Math.max(focusYmax, y1, y2, y3);
2122 }
2123 return true;
2124 }
2125 for (var pts = 0; pts < drawnConics.length; pts += 8) {
2126 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
caryclark55888e42016-07-18 10:01:36 -07002127 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2128 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
caryclark1049f122015-04-20 08:31:59 -07002129 && w == drawnCubics[pts + 6]) {
2130 return true;
2131 }
2132 }
2133 drawnConics.push(x1);
2134 drawnConics.push(y1);
2135 drawnConics.push(x2);
2136 drawnConics.push(y2);
2137 drawnConics.push(x3);
2138 drawnConics.push(y3);
2139 drawnCubics.push(w);
2140 return false;
2141}
2142
2143var kMaxConicToQuadPOW2 = 5;
2144
2145function computeQuadPOW2(curve, tol) {
2146 var a = curve[6] - 1;
2147 var k = a / (4 * (2 + a));
2148 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
2149 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
2150
2151 var error = Math.sqrt(x * x + y * y);
2152 var pow2;
2153 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
2154 if (error <= tol) {
2155 break;
2156 }
2157 error *= 0.25;
2158 }
2159 return pow2;
2160}
2161
2162function subdivide_w_value(w) {
2163 return Math.sqrt(0.5 + w * 0.5);
2164}
2165
2166function chop(curve, part1, part2) {
2167 var w = curve[6];
2168 var scale = 1 / (1 + w);
2169 part1[0] = curve[0];
2170 part1[1] = curve[1];
2171 part1[2] = (curve[0] + curve[2] * w) * scale;
2172 part1[3] = (curve[1] + curve[3] * w) * scale;
2173 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
2174 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
2175 part2[2] = (curve[2] * w + curve[4]) * scale;
2176 part2[3] = (curve[3] * w + curve[5]) * scale;
2177 part2[4] = curve[4];
2178 part2[5] = curve[5];
2179 part1[6] = part2[6] = subdivide_w_value(w);
2180}
2181
2182function subdivide(curve, level, pts) {
2183 if (0 == level) {
2184 pts.push(curve[2]);
2185 pts.push(curve[3]);
2186 pts.push(curve[4]);
2187 pts.push(curve[5]);
2188 } else {
2189 var part1 = [], part2 = [];
2190 chop(curve, part1, part2);
2191 --level;
2192 subdivide(part1, level, pts);
2193 subdivide(part2, level, pts);
2194 }
2195}
2196
2197function chopIntoQuadsPOW2(curve, pow2, pts) {
2198 subdivide(curve, pow2, pts);
2199 return 1 << pow2;
2200}
2201
2202function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
2203 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
2204 return;
2205 }
2206 ctx.beginPath();
2207 ctx.moveTo((x1 - srcLeft) * scale,
2208 (y1 - srcTop) * scale);
2209 var tol = 1 / scale;
2210 var curve = [x1, y1, x2, y2, x3, y3, w];
2211 var pow2 = computeQuadPOW2(curve, tol);
2212 var pts = [];
2213 chopIntoQuadsPOW2(curve, pow2, pts);
2214 for (var i = 0; i < pts.length; i += 4) {
2215 ctx.quadraticCurveTo(
2216 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
2217 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
2218 }
2219 ctx.stroke();
2220}
2221
2222function conic_eval_numerator(x1, x2, x3, w, t) {
2223 var src2w = x2 * w;
2224 var C = x1;
2225 var A = x3 - 2 * src2w + C;
2226 var B = 2 * (src2w - C);
2227 return (A * t + B) * t + C;
2228}
2229
2230
2231function conic_eval_denominator(w, t) {
2232 var B = 2 * (w - 1);
2233 var C = 1;
2234 var A = -B;
2235 return (A * t + B) * t + C;
2236}
2237
2238function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2239 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
2240 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
2241 var az = conic_eval_denominator(w, t1);
2242 var midT = (t1 + t2) / 2;
2243 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
2244 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
2245 var dz = conic_eval_denominator(w, midT);
2246 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
2247 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
2248 var cz = conic_eval_denominator(w, t2);
2249 var bx = 2 * dx - (ax + cx) / 2;
2250 var by = 2 * dy - (ay + cy) / 2;
2251 var bz = 2 * dz - (az + cz) / 2;
2252 var dt = t2 - t1;
2253 var dt_1 = 1 - dt;
caryclark1049f122015-04-20 08:31:59 -07002254 var array = [
caryclarked0935a2015-10-22 07:23:52 -07002255 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, 0
caryclark1049f122015-04-20 08:31:59 -07002256 ];
caryclarked0935a2015-10-22 07:23:52 -07002257 var dMidAC = { x:(array[0] + array[4]) / 2, y:(array[1] + array[5]) / 2 };
2258 var dMid = { x:dx / dz, y:dy / dz };
2259 var dWNumer = { x:dMidAC.x - dMid.x, y:dMidAC.y - dMid.y };
2260 var dWDenom = { x:dMid.x - array[2], y:dMid.y - array[3] };
2261 var partW = Math.sqrt(dWNumer.x * dWNumer.x + dWNumer.y * dWNumer.y)
2262 / Math.sqrt(dWDenom.x * dWDenom.x + dWDenom.y * dWDenom.y);
2263 array[6] = partW;
caryclark1049f122015-04-20 08:31:59 -07002264 return array;
2265}
caryclark55888e42016-07-18 10:01:36 -07002266
caryclark1049f122015-04-20 08:31:59 -07002267function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2268 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2269 var ax = a[0];
2270 var ay = a[1];
2271 var bx = a[2];
2272 var by = a[3];
2273 var cx = a[4];
2274 var cy = a[5];
2275 var w_ = a[6];
2276 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
2277}
2278
caryclarkdac1d172014-06-17 05:15:38 -07002279function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2280 if (collect_bounds) {
2281 if (focus_enabled) {
2282 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
2283 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
2284 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
2285 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
2286 }
2287 return true;
2288 }
2289 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
2290 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
caryclark55888e42016-07-18 10:01:36 -07002291 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2292 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
caryclarkdac1d172014-06-17 05:15:38 -07002293 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
2294 return true;
2295 }
2296 }
2297 drawnCubics.push(x1);
2298 drawnCubics.push(y1);
2299 drawnCubics.push(x2);
2300 drawnCubics.push(y2);
2301 drawnCubics.push(x3);
2302 drawnCubics.push(y3);
2303 drawnCubics.push(x4);
2304 drawnCubics.push(y4);
2305 return false;
2306}
2307
2308function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2309 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
2310 return;
2311 }
2312 ctx.beginPath();
2313 ctx.moveTo((x1 - srcLeft) * scale,
2314 (y1 - srcTop) * scale);
2315 ctx.bezierCurveTo((x2 - srcLeft) * scale,
2316 (y2 - srcTop) * scale,
2317 (x3 - srcLeft) * scale,
2318 (y3 - srcTop) * scale,
2319 (x4 - srcLeft) * scale,
2320 (y4 - srcTop) * scale);
2321 ctx.stroke();
2322}
2323
2324function interp_cubic_coords(x1, x2, x3, x4, t)
2325{
2326 var ab = interp(x1, x2, t);
2327 var bc = interp(x2, x3, t);
2328 var cd = interp(x3, x4, t);
2329 var abc = interp(ab, bc, t);
2330 var bcd = interp(bc, cd, t);
2331 var abcd = interp(abc, bcd, t);
2332 return abcd;
2333}
2334
2335function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2336 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
2337 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
2338 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
2339 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
2340 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
2341 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
2342 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
2343 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
2344 var mx = ex * 27 - ax * 8 - dx;
2345 var my = ey * 27 - ay * 8 - dy;
2346 var nx = fx * 27 - ax - dx * 8;
2347 var ny = fy * 27 - ay - dy * 8;
2348 var bx = (mx * 2 - nx) / 18;
2349 var by = (my * 2 - ny) / 18;
2350 var cx = (nx * 2 - mx) / 18;
2351 var cy = (ny * 2 - my) / 18;
2352 var array = [
2353 ax, ay, bx, by, cx, cy, dx, dy
2354 ];
2355 return array;
2356}
caryclark55888e42016-07-18 10:01:36 -07002357
caryclarkdac1d172014-06-17 05:15:38 -07002358function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2359 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2360 var ax = a[0];
2361 var ay = a[1];
2362 var bx = a[2];
2363 var by = a[3];
2364 var cx = a[4];
2365 var cy = a[5];
2366 var dx = a[6];
2367 var dy = a[7];
2368 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
2369 return;
2370 }
2371 ctx.beginPath();
2372 ctx.moveTo((ax - srcLeft) * scale,
2373 (ay - srcTop) * scale);
2374 ctx.bezierCurveTo((bx - srcLeft) * scale,
2375 (by - srcTop) * scale,
2376 (cx - srcLeft) * scale,
2377 (cy - srcTop) * scale,
2378 (dx - srcLeft) * scale,
2379 (dy - srcTop) * scale);
2380 ctx.stroke();
2381}
2382
2383function drawCurve(c) {
2384 switch (c.length) {
2385 case 4:
2386 drawLine(c[0], c[1], c[2], c[3]);
2387 break;
2388 case 6:
2389 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
2390 break;
caryclark1049f122015-04-20 08:31:59 -07002391 case 7:
2392 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
2393 break;
caryclarkdac1d172014-06-17 05:15:38 -07002394 case 8:
2395 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
2396 break;
2397 }
2398}
2399
2400function boundsWidth(pts) {
2401 var min = pts[0];
2402 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07002403 var length = pts.length == 7 ? 6 : pts.length;
2404 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002405 min = Math.min(min, pts[idx]);
2406 max = Math.max(max, pts[idx]);
2407 }
2408 return max - min;
2409}
2410
2411function boundsHeight(pts) {
2412 var min = pts[1];
2413 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07002414 var length = pts.length == 7 ? 6 : pts.length;
2415 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002416 min = Math.min(min, pts[idx]);
2417 max = Math.max(max, pts[idx]);
2418 }
2419 return max - min;
2420}
2421
2422function tangent(pts) {
2423 var dx = pts[2] - pts[0];
2424 var dy = pts[3] - pts[1];
2425 if (dx == 0 && dy == 0 && pts.length > 4) {
2426 dx = pts[4] - pts[0];
2427 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002428 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002429 dx = pts[6] - pts[0];
2430 dy = pts[7] - pts[1];
2431 }
2432 }
2433 return Math.atan2(-dy, dx);
2434}
2435
2436function hodograph(cubic) {
2437 var hodo = [];
2438 hodo[0] = 3 * (cubic[2] - cubic[0]);
2439 hodo[1] = 3 * (cubic[3] - cubic[1]);
2440 hodo[2] = 3 * (cubic[4] - cubic[2]);
2441 hodo[3] = 3 * (cubic[5] - cubic[3]);
2442 hodo[4] = 3 * (cubic[6] - cubic[4]);
2443 hodo[5] = 3 * (cubic[7] - cubic[5]);
2444 return hodo;
2445}
2446
2447function hodograph2(cubic) {
2448 var quad = hodograph(cubic);
2449 var hodo = [];
2450 hodo[0] = 2 * (quad[2] - quad[0]);
2451 hodo[1] = 2 * (quad[3] - quad[1]);
2452 hodo[2] = 2 * (quad[4] - quad[2]);
2453 hodo[3] = 2 * (quad[5] - quad[3]);
2454 return hodo;
2455}
2456
2457function quadraticRootsReal(A, B, C, s) {
2458 if (A == 0) {
2459 if (B == 0) {
2460 s[0] = 0;
2461 return C == 0;
2462 }
2463 s[0] = -C / B;
2464 return 1;
2465 }
2466 /* normal form: x^2 + px + q = 0 */
2467 var p = B / (2 * A);
2468 var q = C / A;
2469 var p2 = p * p;
2470 if (p2 < q) {
2471 return 0;
2472 }
2473 var sqrt_D = 0;
2474 if (p2 > q) {
2475 sqrt_D = sqrt(p2 - q);
2476 }
2477 s[0] = sqrt_D - p;
2478 s[1] = -sqrt_D - p;
2479 return 1 + s[0] != s[1];
2480}
2481
2482function add_valid_ts(s, realRoots, t) {
2483 var foundRoots = 0;
2484 for (var index = 0; index < realRoots; ++index) {
2485 var tValue = s[index];
2486 if (tValue >= 0 && tValue <= 1) {
2487 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2488 if (t[idx2] != tValue) {
2489 t[foundRoots++] = tValue;
2490 }
2491 }
2492 }
2493 }
2494 return foundRoots;
2495}
2496
2497function quadraticRootsValidT(a, b, c, t) {
2498 var s = [];
2499 var realRoots = quadraticRootsReal(A, B, C, s);
2500 var foundRoots = add_valid_ts(s, realRoots, t);
2501 return foundRoots != 0;
2502}
2503
2504function find_cubic_inflections(cubic, tValues) {
2505 var Ax = src[2] - src[0];
2506 var Ay = src[3] - src[1];
2507 var Bx = src[4] - 2 * src[2] + src[0];
2508 var By = src[5] - 2 * src[3] + src[1];
2509 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2510 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2511 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2512 Ax * By - Ay * Bx, tValues);
2513}
2514
2515function dxy_at_t(curve, type, t) {
2516 var dxy = {};
Cary Clarkff114282016-12-14 11:56:16 -05002517 if (type == PATH_LINE) {
2518 dxy.x = curve[2] - curve[0];
2519 dxy.y = curve[3] - curve[1];
2520 } else if (type == PATH_QUAD) {
caryclarkdac1d172014-06-17 05:15:38 -07002521 var a = t - 1;
2522 var b = 1 - 2 * t;
2523 var c = t;
2524 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2525 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002526 } else if (type == PATH_CONIC) {
2527 var p20x = curve[4] - curve[0];
2528 var p20y = curve[5] - curve[1];
2529 var p10xw = (curve[2] - curve[0]) * curve[6];
2530 var p10yw = (curve[3] - curve[1]) * curve[6];
2531 var coeff0x = curve[6] * p20x - p20x;
2532 var coeff0y = curve[6] * p20y - p20y;
2533 var coeff1x = p20x - 2 * p10xw;
2534 var coeff1y = p20y - 2 * p10yw;
2535 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2536 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002537 } else if (type == PATH_CUBIC) {
2538 var one_t = 1 - t;
2539 var a = curve[0];
2540 var b = curve[2];
2541 var c = curve[4];
2542 var d = curve[6];
2543 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2544 a = curve[1];
2545 b = curve[3];
2546 c = curve[5];
2547 d = curve[7];
2548 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2549 }
2550 return dxy;
2551}
2552
Ben Wagner29380bd2017-10-09 14:43:00 -04002553function dpt_at_t(curve, t) {
Cary Clarkff114282016-12-14 11:56:16 -05002554 var type = PATH_LINE + (curve.length / 2 - 2);
Ben Wagner29380bd2017-10-09 14:43:00 -04002555 return dxy_at_t(curve, type, t);
Cary Clarkff114282016-12-14 11:56:16 -05002556}
2557
caryclarkdac1d172014-06-17 05:15:38 -07002558function drawLabel(num, px, py) {
2559 ctx.beginPath();
2560 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2561 ctx.closePath();
2562 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2563 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2564 ctx.stroke();
2565 ctx.fillStyle = "black";
2566 ctx.font = "normal 10px Arial";
2567 // ctx.rotate(0.001);
2568 ctx.fillText(num, px - 2, py + 3);
2569 // ctx.rotate(-0.001);
2570}
2571
2572function drawLabelX(ymin, num, loc) {
2573 var px = (loc - srcLeft) * scale;
2574 var py = (ymin - srcTop) * scale - 20;
2575 drawLabel(num, px, py);
2576}
2577
2578function drawLabelY(xmin, num, loc) {
2579 var px = (xmin - srcLeft) * scale - 20;
2580 var py = (loc - srcTop) * scale;
2581 drawLabel(num, px, py);
2582}
2583
2584function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2585 ctx.beginPath();
2586 ctx.moveTo(hx, hy - 100);
2587 ctx.lineTo(hx, hy);
2588 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2589 ctx.stroke();
2590 ctx.beginPath();
2591 ctx.moveTo(hx, hy);
2592 ctx.lineTo(hx, hy + 100);
2593 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2594 ctx.stroke();
2595 ctx.beginPath();
2596 ctx.moveTo(hx - 100, hy);
2597 ctx.lineTo(hx, hy);
2598 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2599 ctx.stroke();
2600 ctx.beginPath();
2601 ctx.moveTo(hx, hy);
2602 ctx.lineTo(hx + 100, hy);
2603 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2604 ctx.stroke();
2605}
2606
2607function scalexy(x, y, mag) {
2608 var length = Math.sqrt(x * x + y * y);
2609 return mag / length;
2610}
2611
caryclark03b03ca2015-04-23 09:13:37 -07002612function drawArrow(x, y, dx, dy, s) {
2613 var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
caryclarkdac1d172014-06-17 05:15:38 -07002614 dx *= dscale;
2615 dy *= dscale;
2616 ctx.beginPath();
2617 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2618 x += dx;
2619 y += dy;
2620 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2621 dx /= 10;
2622 dy /= 10;
2623 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2624 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2625 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2626 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2627 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2628 ctx.stroke();
2629}
2630
2631function x_at_t(curve, t) {
2632 var one_t = 1 - t;
2633 if (curve.length == 4) {
2634 return one_t * curve[0] + t * curve[2];
2635 }
2636 var one_t2 = one_t * one_t;
2637 var t2 = t * t;
2638 if (curve.length == 6) {
2639 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2640 }
caryclark1049f122015-04-20 08:31:59 -07002641 if (curve.length == 7) {
2642 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2643 / (one_t2 +2 * one_t * t * curve[6] + t2);
2644 }
caryclarkdac1d172014-06-17 05:15:38 -07002645 var a = one_t2 * one_t;
2646 var b = 3 * one_t2 * t;
2647 var c = 3 * one_t * t2;
2648 var d = t2 * t;
2649 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2650}
2651
2652function y_at_t(curve, t) {
2653 var one_t = 1 - t;
2654 if (curve.length == 4) {
2655 return one_t * curve[1] + t * curve[3];
2656 }
2657 var one_t2 = one_t * one_t;
2658 var t2 = t * t;
2659 if (curve.length == 6) {
2660 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2661 }
caryclark1049f122015-04-20 08:31:59 -07002662 if (curve.length == 7) {
2663 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2664 / (one_t2 +2 * one_t * t * curve[6] + t2);
2665 }
caryclarkdac1d172014-06-17 05:15:38 -07002666 var a = one_t2 * one_t;
2667 var b = 3 * one_t2 * t;
2668 var c = 3 * one_t * t2;
2669 var d = t2 * t;
2670 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2671}
2672
Ben Wagner29380bd2017-10-09 14:43:00 -04002673function pt_at_t(curve, t) {
2674 var pt = {};
2675 pt.x = x_at_t(curve, t);
2676 pt.y = y_at_t(curve, t);
2677 return pt;
Cary Clarkff114282016-12-14 11:56:16 -05002678}
2679
2680function drawOrder(curve, t, label) {
2681 var px = x_at_t(curve, t);
2682 var py = y_at_t(curve, t);
caryclarkdac1d172014-06-17 05:15:38 -07002683 var _px = (px - srcLeft) * scale;
2684 var _py = (py - srcTop) * scale;
2685 ctx.beginPath();
2686 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2687 ctx.closePath();
2688 ctx.fillStyle = "white";
2689 ctx.fill();
2690 if (label == 'L') {
2691 ctx.strokeStyle = "rgba(255,0,0, 1)";
2692 ctx.fillStyle = "rgba(255,0,0, 1)";
2693 } else {
2694 ctx.strokeStyle = "rgba(0,0,255, 1)";
2695 ctx.fillStyle = "rgba(0,0,255, 1)";
2696 }
2697 ctx.stroke();
2698 ctx.font = "normal 16px Arial";
2699 ctx.textAlign = "center";
2700 ctx.fillText(label, _px, _py + 5);
2701 ctx.font = "normal 10px Arial";
2702}
2703
Ben Wagner29380bd2017-10-09 14:43:00 -04002704function drawVisibleOrder(curve, label) {
2705 var s = pt_at_t(curve, 0);
2706 var e = pt_at_t(curve, 1);
2707 var sOn = ptOnScreen(s);
2708 var eOn = ptOnScreen(e);
2709 var defaultT = 0.85;
2710 if (sOn && eOn)
2711 return drawOrder(curve, defaultT, label);
2712 if (sOn || eOn) {
2713 if (eOn) {
2714 defaultT = 1 - defaultT;
2715 }
2716 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2717 var t = defaultT;
2718 var tries = 16;
2719 do {
2720 var mid = pt_at_t(curve, t);
2721 if (ptOnScreen(mid))
2722 return drawOrder(curve, t, label);
2723 t += step;
2724 step /= 2;
2725 } while (--tries > 0);
2726 drawOrder(curve, defaultT, label);
2727 }
2728 // scattershot until we find a visible point
2729 var denom = 2; // visit odd number num / denom to hit unique pts
2730 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2731 do {
2732 for (var numer = 1; numer < denom; numer += 2) {
2733 var t = numer / denom + 0.1;
2734 if (t >= 1) {
2735 break;
2736 }
2737 var mid = pt_at_t(curve, t);
2738 if (ptOnScreen(mid))
2739 return drawOrder(curve, t, label);
2740 }
2741 denom *= 2;
2742 } while (--tries > 0);
2743 drawOrder(curve, defaultT, label);
Cary Clarkff114282016-12-14 11:56:16 -05002744}
2745
Ben Wagner29380bd2017-10-09 14:43:00 -04002746function set_length(pt, newLen) {
2747 var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
2748 var scale = newLen / len;
2749 var newPt = { x: pt.x * scale, y: pt.y * scale };
2750 return newPt;
Cary Clarkff114282016-12-14 11:56:16 -05002751}
2752
Ben Wagner29380bd2017-10-09 14:43:00 -04002753function drawDirection(curve, t) {
Cary Clarkff114282016-12-14 11:56:16 -05002754 var d = dpt_at_t(curve, t);
2755 d = set_length(d, 16);
Ben Wagner29380bd2017-10-09 14:43:00 -04002756 var pt = localToGlobal(pt_at_t(curve, t));
Cary Clarkff114282016-12-14 11:56:16 -05002757 ctx.beginPath();
2758 ctx.moveTo(pt.x - d.y, pt.y + d.x);
2759 ctx.lineTo(pt.x + d.x, pt.y + d.y);
2760 ctx.lineTo(pt.x + d.y, pt.y - d.x);
2761 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2762 ctx.stroke();
2763}
2764
Ben Wagner29380bd2017-10-09 14:43:00 -04002765function drawVisibleDirection(curve) {
2766 var s = pt_at_t(curve, 0);
2767 var e = pt_at_t(curve, 1);
2768 var sOn = ptOnScreen(s);
2769 var eOn = ptOnScreen(e);
2770 var defaultT = 0.65;
2771 if (sOn && eOn) {
2772 return drawDirection(curve, defaultT);
2773 }
2774 if (sOn || eOn) {
2775 if (eOn) {
2776 defaultT = 1 - defaultT;
2777 }
2778 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2779 var t = defaultT;
2780 var tries = 16;
2781 do {
2782 var mid = pt_at_t(curve, t);
2783 if (ptOnScreen(mid))
2784 return drawDirection(curve, t);
2785 t += step;
2786 step /= 2;
2787 } while (--tries > 0);
2788 drawDirection(curve, defaultT);
2789 }
2790 // scattershot until we find a visible point
2791 var denom = 2; // visit odd number num / denom to hit unique pts
2792 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2793 do {
2794 for (var numer = 1; numer < denom; numer += 2) {
2795 var t = numer / denom + 0.1;
2796 if (t >= 1) {
2797 break;
2798 }
2799 var mid = pt_at_t(curve, t);
2800 if (ptOnScreen(mid))
2801 return drawDirection(curve, t);
2802 }
2803 denom *= 2;
2804 } while (--tries > 0);
2805 drawDirection(curve, defaultT);
Cary Clarkff114282016-12-14 11:56:16 -05002806}
2807
2808function drawID(curve, t, id) {
2809 var px = x_at_t(curve, t);
2810 var py = y_at_t(curve, t);
caryclarkdac1d172014-06-17 05:15:38 -07002811 var _px = (px - srcLeft) * scale;
2812 var _py = (py - srcTop) * scale;
2813 draw_id_at(id, _px, _py);
2814}
2815
Ben Wagner29380bd2017-10-09 14:43:00 -04002816function localToGlobal(local) {
2817 var global = {};
2818 global.x = (local.x - srcLeft) * scale;
2819 global.y = (local.y - srcTop) * scale;
2820 return global;
Cary Clarkff114282016-12-14 11:56:16 -05002821}
2822
Ben Wagner29380bd2017-10-09 14:43:00 -04002823function ptOnScreen(local) {
2824 var pt = localToGlobal(local);
2825 return 10 <= pt.x && pt.x <= screenWidth - 10
2826 && 10 <= pt.y && pt.y <= screenHeight - 10;
Cary Clarkff114282016-12-14 11:56:16 -05002827}
2828
Ben Wagner29380bd2017-10-09 14:43:00 -04002829function drawVisibleID(curve, defaultT, id) {
2830 // determine if either or both ends are visible
2831 var s = pt_at_t(curve, 0);
2832 var e = pt_at_t(curve, 1);
2833 var sOn = ptOnScreen(s);
2834 var eOn = ptOnScreen(e);
2835 if (sOn && eOn)
2836 return drawID(curve, defaultT, id);
2837 if (sOn || eOn) {
2838 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2839 var t = defaultT;
2840 var tries = 16;
2841 do {
2842 var mid = pt_at_t(curve, t);
2843 if (ptOnScreen(mid))
2844 return drawID(curve, t, id);
2845 t += step;
2846 step /= 2;
2847 } while (--tries > 0);
2848 drawID(curve, defaultT, id);
2849 }
2850 // scattershot until we find a visible point
2851 var denom = 2; // visit odd number num / denom to hit unique pts
2852 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2853 do {
2854 for (var numer = 1; numer < denom; numer += 2) {
2855 var t = numer / denom;
2856 var mid = pt_at_t(curve, t);
2857 if (ptOnScreen(mid))
2858 return drawID(curve, t, id);
2859 }
2860 denom *= 2;
2861 } while (--tries > 0);
2862 drawID(curve, defaultT, id);
Cary Clarkff114282016-12-14 11:56:16 -05002863}
2864
caryclarkdac1d172014-06-17 05:15:38 -07002865function draw_id_at(id, _px, _py) {
2866 ctx.beginPath();
2867 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2868 ctx.closePath();
2869 ctx.fillStyle = "white";
2870 ctx.fill();
2871 ctx.strokeStyle = "rgba(127,127,0, 1)";
2872 ctx.fillStyle = "rgba(127,127,0, 1)";
2873 ctx.stroke();
2874 ctx.font = "normal 16px Arial";
2875 ctx.textAlign = "center";
2876 ctx.fillText(id, _px, _py + 5);
2877 ctx.font = "normal 10px Arial";
2878}
2879
2880function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2881 var curve = [x1, y1, x2, y2];
2882 drawCurvePartialID(id, curve, t1, t2);
2883}
2884
caryclark55888e42016-07-18 10:01:36 -07002885function drawLineID(id, x1, y1, x2, y2) {
2886 drawLinePartialID(id, x1, y1, x2, y2, 0, 1);
2887}
2888
caryclarkdac1d172014-06-17 05:15:38 -07002889function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2890 var curve = [x1, y1, x2, y2, x3, y3];
2891 drawCurvePartialID(id, curve, t1, t2);
2892}
2893
caryclark55888e42016-07-18 10:01:36 -07002894function drawQuadID(id, x1, y1, x2, y2, x3, y3) {
2895 drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, 0, 1);
2896}
2897
caryclark1049f122015-04-20 08:31:59 -07002898function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2899 var curve = [x1, y1, x2, y2, x3, y3, w];
2900 drawCurvePartialID(id, curve, t1, t2);
2901}
2902
caryclark55888e42016-07-18 10:01:36 -07002903function drawConicID(id, x1, y1, x2, y2, x3, y3, w) {
2904 drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, 0, 1);
2905}
2906
caryclarkdac1d172014-06-17 05:15:38 -07002907function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2908 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2909 drawCurvePartialID(id, curve, t1, t2);
2910}
2911
caryclark55888e42016-07-18 10:01:36 -07002912function drawCubicID(id, x1, y1, x2, y2, x3, y3, x4, y4) {
2913 drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, 0, 1);
2914}
2915
caryclarkdac1d172014-06-17 05:15:38 -07002916function drawCurvePartialID(id, curve, t1, t2) {
Cary Clarkff114282016-12-14 11:56:16 -05002917 drawVisibleID(curve, (t1 + t2) / 2, id);
caryclarkdac1d172014-06-17 05:15:38 -07002918}
2919
2920function drawCurveSpecials(test, curve, type) {
2921 if (pt_labels) {
2922 drawPoints(curve, type, pt_labels == 2);
2923 }
2924 if (control_lines != 0) {
2925 drawControlLines(curve, type, control_lines);
2926 }
2927 if (curve_t) {
2928 drawPointAtT(curve, type);
2929 }
2930 if (draw_midpoint) {
2931 var mid = pointAtT(curve, type, 0.5);
2932 drawPoint(mid.x, mid.y, true);
2933 }
2934 if (draw_id) {
2935 var id = idByCurve(test, curve, type);
2936 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05002937 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07002938 }
2939 }
Ben Wagner29380bd2017-10-09 14:43:00 -04002940 if (draw_direction) {
2941 drawVisibleDirection(curve);
Cary Clarkff114282016-12-14 11:56:16 -05002942 }
caryclarkdac1d172014-06-17 05:15:38 -07002943 if (type == PATH_LINE) {
2944 return;
2945 }
2946 if (draw_deriviatives > 0) {
2947 var d = dxy_at_t(curve, type, 0);
caryclark03b03ca2015-04-23 09:13:37 -07002948 drawArrow(curve[0], curve[1], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002949 if (draw_deriviatives == 2) {
2950 d = dxy_at_t(curve, type, 1);
2951 if (type == PATH_CUBIC) {
caryclark03b03ca2015-04-23 09:13:37 -07002952 drawArrow(curve[6], curve[7], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002953 } else {
caryclark03b03ca2015-04-23 09:13:37 -07002954 drawArrow(curve[4], curve[5], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002955 }
2956 }
2957 if (draw_midpoint) {
2958 var mid = pointAtT(curve, type, 0.5);
2959 d = dxy_at_t(curve, type, 0.5);
caryclark03b03ca2015-04-23 09:13:37 -07002960 drawArrow(mid.x, mid.y, d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002961 }
2962 }
2963 if (type != PATH_CUBIC) {
2964 return;
2965 }
caryclarkdac1d172014-06-17 05:15:38 -07002966 if (draw_sequence) {
2967 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2968 for (var i = 0; i < 8; i+= 2) {
2969 drawLabelX(ymin, i >> 1, curve[i]);
2970 }
2971 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2972 for (var i = 1; i < 8; i+= 2) {
2973 drawLabelY(xmin, i >> 1, curve[i]);
2974 }
2975 }
2976}
2977
2978function logCurves(test) {
2979 for (curves in test) {
2980 var curve = test[curves];
2981 dumpCurve(curve);
2982 }
2983}
2984
2985function curveToString(curve) {
2986 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002987 var length = curve.length == 7 ? 6 : curve.length;
2988 if (curve.length == 7) {
2989 str += "{";
2990 }
2991 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002992 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2993 if (i < curve.length - 2) {
2994 str += "}, {";
2995 }
2996 }
caryclark1049f122015-04-20 08:31:59 -07002997 str += "}";
2998 if (curve.length == 7) {
2999 str += "}, " + curve[6].toFixed(decimal_places);
3000 }
3001 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07003002 return str;
3003}
3004
3005function dumpCurve(curve) {
3006 console.log(curveToString(curve));
3007}
3008
3009function draw(test, lines, title) {
3010 ctx.fillStyle = "rgba(0,0,0, 0.1)";
3011 ctx.font = "normal 50px Arial";
3012 ctx.textAlign = "left";
3013 ctx.fillText(title, 50, 50);
3014 ctx.font = "normal 10px Arial";
3015 ctx.lineWidth = "1.001"; "0.999";
3016 var secondPath = test.length;
3017 var closeCount = 0;
3018 logStart = -1;
3019 logRange = 0;
3020 // find last active rec type at this step
3021 var curType = test[0];
3022 var curStep = 0;
3023 var hasOp = false;
3024 var lastActive = 0;
3025 var lastAdd = 0;
caryclark624637c2015-05-11 07:21:27 -07003026 var lastCoin = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003027 var lastSect = 0;
3028 var lastSort = 0;
3029 var lastMark = 0;
caryclark03b03ca2015-04-23 09:13:37 -07003030 var lastTop = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003031 activeCount = 0;
3032 addCount = 0;
3033 angleCount = 0;
3034 opCount = 0;
3035 sectCount = 0;
3036 sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -07003037 topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003038 markCount = 0;
3039 activeMax = 0;
3040 addMax = 0;
3041 angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -07003042 coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003043 opMax = 0;
3044 sectMax = 0;
3045 sectMax2 = 0;
3046 sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -07003047 topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003048 markMax = 0;
3049 lastIndex = test.length - 3;
3050 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
3051 var recType = test[tIndex];
3052 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
3053 console.log("unknown rec type: " + recType);
3054 throw "stop execution";
3055 }
3056 // if (curType == recType && curType != REC_TYPE_ADD) {
3057 // continue;
3058 // }
3059 var inStepRange = step_limit == 0 || curStep < step_limit;
3060 curType = recType;
3061 if (recType == REC_TYPE_OP) {
3062 hasOp = true;
3063 continue;
3064 }
3065 if (recType == REC_TYPE_UNKNOWN) {
3066 // these types do not advance step
3067 continue;
3068 }
3069 var bumpStep = false;
3070 var records = test[tIndex + 2];
3071 var fragType = records[0];
3072 if (recType == REC_TYPE_ADD) {
3073 if (records.length != 2) {
3074 console.log("expect only two elements: " + records.length);
3075 throw "stop execution";
3076 }
3077 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
3078 continue;
3079 }
3080 ++addMax;
3081 if (!draw_add || !inStepRange) {
3082 continue;
3083 }
3084 lastAdd = tIndex;
3085 ++addCount;
3086 bumpStep = true;
3087 }
3088 if (recType == REC_TYPE_PATH && hasOp) {
3089 secondPath = tIndex;
3090 }
caryclark54359292015-03-26 07:52:43 -07003091 if (recType == REC_TYPE_PATH2 && hasOp) {
3092 secondPath = tIndex;
3093 }
caryclarkdac1d172014-06-17 05:15:38 -07003094 if (recType == REC_TYPE_ACTIVE) {
3095 ++activeMax;
3096 if (!draw_active || !inStepRange) {
3097 continue;
3098 }
3099 lastActive = tIndex;
3100 ++activeCount;
3101 bumpStep = true;
3102 }
3103 if (recType == REC_TYPE_ACTIVE_OP) {
3104 ++opMax;
3105 if (!draw_op || !inStepRange) {
3106 continue;
3107 }
3108 lastOp = tIndex;
3109 ++opCount;
3110 bumpStep = true;
3111 }
caryclark54359292015-03-26 07:52:43 -07003112 if (recType == REC_TYPE_AFTERPART) {
3113 if (draw_angle != 3 || !inStepRange) {
3114 continue;
3115 }
3116 lastAngle = tIndex;
3117 ++angleCount;
3118 bumpStep = true;
3119 }
caryclarkdac1d172014-06-17 05:15:38 -07003120 if (recType == REC_TYPE_ANGLE) {
3121 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07003122 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07003123 continue;
3124 }
3125 lastAngle = tIndex;
3126 ++angleCount;
3127 bumpStep = true;
3128 }
caryclark624637c2015-05-11 07:21:27 -07003129 if (recType == REC_TYPE_COINCIDENCE) {
3130 ++coinMax;
3131 if (!draw_coincidence || !inStepRange) {
3132 continue;
3133 }
3134 lastCoin = tIndex;
3135 ++coinCount;
3136 bumpStep = true;
3137 }
caryclarkdac1d172014-06-17 05:15:38 -07003138 if (recType == REC_TYPE_SECT) {
3139 if (records.length != 2) {
3140 console.log("expect only two elements: " + records.length);
3141 throw "stop execution";
3142 }
3143 ++sectMax;
3144 var sectBump = 1;
3145 switch (fragType) {
3146 case INTERSECT_LINE:
3147 case INTERSECT_QUAD_LINE:
3148 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003149 case INTERSECT_CONIC_LINE:
caryclark55888e42016-07-18 10:01:36 -07003150 case INTERSECT_CONIC_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003151 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07003152 case INTERSECT_SELF_CUBIC:
3153 case INTERSECT_CUBIC_LINE:
3154 case INTERSECT_CUBIC_QUAD:
3155 case INTERSECT_CUBIC:
3156 sectBump = 1;
3157 break;
3158 case INTERSECT_LINE_2:
3159 case INTERSECT_QUAD_LINE_2:
3160 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07003161 case INTERSECT_CONIC_LINE_2:
caryclark55888e42016-07-18 10:01:36 -07003162 case INTERSECT_CONIC_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07003163 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07003164 case INTERSECT_CUBIC_LINE_2:
3165 case INTERSECT_CUBIC_QUAD_2:
3166 case INTERSECT_CUBIC_2:
3167 sectBump = 2;
3168 break;
3169 case INTERSECT_LINE_NO:
3170 case INTERSECT_QUAD_LINE_NO:
3171 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07003172 case INTERSECT_CONIC_LINE_NO:
caryclark55888e42016-07-18 10:01:36 -07003173 case INTERSECT_CONIC_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07003174 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07003175 case INTERSECT_SELF_CUBIC_NO:
3176 case INTERSECT_CUBIC_LINE_NO:
3177 case INTERSECT_CUBIC_QUAD_NO:
3178 case INTERSECT_CUBIC_NO:
3179 sectBump = 0;
3180 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003181 case INTERSECT_CONIC_QUAD_3:
caryclarkdac1d172014-06-17 05:15:38 -07003182 case INTERSECT_CUBIC_LINE_3:
3183 case INTERSECT_CUBIC_QUAD_3:
3184 case INTERSECT_CUBIC_3:
3185 sectBump = 3;
3186 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003187 case INTERSECT_CONIC_QUAD_4:
caryclarkdac1d172014-06-17 05:15:38 -07003188 case INTERSECT_CUBIC_QUAD_4:
3189 case INTERSECT_CUBIC_4:
3190 sectBump = 4;
3191 break;
3192 default:
3193 console.log("missing case " + records.length);
3194 throw "stop execution";
3195 }
3196 sectMax2 += sectBump;
3197 if (draw_intersection <= 1 || !inStepRange) {
3198 continue;
3199 }
3200 lastSect = tIndex;
3201 sectCount += sectBump;
3202 bumpStep = true;
3203 }
3204 if (recType == REC_TYPE_SORT) {
3205 ++sortMax;
3206 if (!draw_sort || !inStepRange) {
3207 continue;
3208 }
3209 lastSort = tIndex;
3210 ++sortCount;
3211 bumpStep = true;
3212 }
caryclark03b03ca2015-04-23 09:13:37 -07003213 if (recType == REC_TYPE_TOP) {
3214 ++topMax;
3215 if (!draw_top || !inStepRange) {
3216 continue;
3217 }
3218 lastTop = tIndex;
3219 ++topCount;
3220 bumpStep = true;
3221 }
caryclarkdac1d172014-06-17 05:15:38 -07003222 if (recType == REC_TYPE_MARK) {
3223 ++markMax;
3224 if (!draw_mark || !inStepRange) {
3225 continue;
3226 }
3227 lastMark = tIndex;
3228 ++markCount;
3229 bumpStep = true;
3230 }
3231 if (bumpStep) {
3232 lastIndex = tIndex;
3233 logStart = test[tIndex + 1];
3234 logRange = records.length / 2;
3235 ++curStep;
3236 }
3237 }
3238 stepMax = (draw_add ? addMax : 0)
3239 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07003240 + (draw_angle ? angleMax : 0)
caryclark624637c2015-05-11 07:21:27 -07003241 + (draw_coincidence ? coinMax : 0)
caryclark54359292015-03-26 07:52:43 -07003242 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07003243 + (draw_sort ? sortMax : 0)
caryclark03b03ca2015-04-23 09:13:37 -07003244 + (draw_top ? topMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07003245 + (draw_mark ? markMax : 0)
3246 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
3247 if (stepMax == 0) {
caryclark624637c2015-05-11 07:21:27 -07003248 stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax;
caryclarkdac1d172014-06-17 05:15:38 -07003249 }
3250 drawnPts = [];
3251 drawnLines = [];
3252 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07003253 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07003254 drawnCubics = [];
3255 focusXmin = focusYmin = Infinity;
3256 focusXmax = focusYmax = -Infinity;
3257 var pathIndex = 0;
3258 var opLetter = 'S';
3259 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
3260 var recType = test[tIndex];
3261 var records = test[tIndex + 2];
3262 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3263 var fragType = records[recordIndex];
3264 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
3265 console.log("unknown in range frag type: " + fragType);
3266 throw "stop execution";
3267 }
3268 var frags = records[recordIndex + 1];
3269 focus_enabled = false;
3270 switch (recType) {
3271 case REC_TYPE_COMPUTED:
3272 if (draw_computed == 0) {
3273 continue;
3274 }
3275 ctx.lineWidth = 1;
3276 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
3277 ctx.fillStyle = "blue";
3278 var drawThis = false;
3279 switch (fragType) {
3280 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003281 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
3282 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07003283 drawQuad(frags[0], frags[1], frags[2], frags[3],
3284 frags[4], frags[5]);
3285 drawThis = true;
3286 }
3287 break;
caryclark1049f122015-04-20 08:31:59 -07003288 case PATH_CONIC:
3289 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
3290 && (draw_computed & 7) == pathIndex)) {
3291 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3292 frags[4], frags[5], frags[6]);
3293 drawThis = true;
3294 }
3295 break;
caryclarkdac1d172014-06-17 05:15:38 -07003296 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07003297 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
3298 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07003299 drawCubic(frags[0], frags[1], frags[2], frags[3],
3300 frags[4], frags[5], frags[6], frags[7]);
3301 drawThis = true;
3302 }
3303 ++pathIndex;
3304 break;
3305 case COMPUTED_SET_1:
3306 pathIndex = 0;
3307 break;
3308 case COMPUTED_SET_2:
3309 pathIndex = 1;
3310 break;
3311 default:
3312 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
3313 throw "stop execution";
3314 }
3315 if (!drawThis || collect_bounds) {
3316 break;
3317 }
3318 drawCurveSpecials(test, frags, fragType);
3319 break;
caryclark26ad22a2015-10-16 09:03:38 -07003320 case REC_TYPE_ALIGNED:
3321 if (draw_path < 4) {
3322 continue;
3323 }
caryclarkdac1d172014-06-17 05:15:38 -07003324 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07003325 case REC_TYPE_PATH2:
caryclark26ad22a2015-10-16 09:03:38 -07003326 if (REC_TYPE_ALIGNED != recType && draw_path >= 4) {
3327 continue;
3328 }
caryclarkdac1d172014-06-17 05:15:38 -07003329 if (!draw_path) {
3330 continue;
3331 }
3332 var firstPath = tIndex < secondPath;
3333 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
3334 continue;
3335 }
3336 ctx.lineWidth = 1;
3337 ctx.strokeStyle = firstPath ? "black" : "red";
3338 ctx.fillStyle = "blue";
caryclark55888e42016-07-18 10:01:36 -07003339 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07003340 switch (fragType) {
3341 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07003342 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
3343 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07003344 break;
3345 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07003346 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
3347 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
3348 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07003349 break;
caryclark1049f122015-04-20 08:31:59 -07003350 case PATH_CONIC:
3351 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
3352 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
3353 frags2[4], frags2[5], frags2[6]);
3354 break;
caryclarkdac1d172014-06-17 05:15:38 -07003355 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07003356 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
3357 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
3358 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07003359 break;
3360 default:
caryclark26ad22a2015-10-16 09:03:38 -07003361 console.log("unknown " + recType + " frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07003362 throw "stop execution";
3363 }
3364 if (collect_bounds) {
3365 break;
3366 }
caryclark54359292015-03-26 07:52:43 -07003367 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07003368 break;
3369 case REC_TYPE_OP:
3370 switch (fragType) {
3371 case OP_INTERSECT: opLetter = 'I'; break;
3372 case OP_DIFFERENCE: opLetter = 'D'; break;
3373 case OP_UNION: opLetter = 'U'; break;
3374 case OP_XOR: opLetter = 'X'; break;
3375 default:
3376 console.log("unknown REC_TYPE_OP frag type: " + fragType);
3377 throw "stop execution";
3378 }
3379 break;
3380 case REC_TYPE_ACTIVE:
3381 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
3382 continue;
3383 }
3384 var x1 = frags[SPAN_X1];
3385 var y1 = frags[SPAN_Y1];
3386 var x2 = frags[SPAN_X2];
3387 var y2 = frags[SPAN_Y2];
caryclark55888e42016-07-18 10:01:36 -07003388 var x3, y3, x3, y4, w;
caryclarkdac1d172014-06-17 05:15:38 -07003389 ctx.lineWidth = 3;
3390 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3391 focus_enabled = true;
3392 switch (fragType) {
3393 case ACTIVE_LINE_SPAN:
caryclark55888e42016-07-18 10:01:36 -07003394 drawLine(x1, y1, x2, y2);
caryclarkdac1d172014-06-17 05:15:38 -07003395 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003396 drawLineID(frags[0], x1, y1, x2, y2);
3397 }
3398 if (pt_labels) {
3399 var curve = [x1, y1, x2, y2];
3400 ctx.fillStyle = "blue";
3401 drawPoints(curve, PATH_LINE, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003402 }
3403 break;
3404 case ACTIVE_QUAD_SPAN:
3405 x3 = frags[SPAN_X3];
3406 y3 = frags[SPAN_Y3];
caryclark55888e42016-07-18 10:01:36 -07003407 drawQuad(x1, y1, x2, y2, x3, y3);
caryclarkdac1d172014-06-17 05:15:38 -07003408 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003409 drawQuadID(frags[0], x1, y1, x2, y2, x3, y3);
3410 }
3411 if (pt_labels) {
3412 var curve = [x1, y1, x2, y2, x3, y3];
3413 ctx.fillStyle = "blue";
3414 drawPoints(curve, PATH_QUAD, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003415 }
3416 break;
caryclark1049f122015-04-20 08:31:59 -07003417 case ACTIVE_CONIC_SPAN:
3418 x3 = frags[SPAN_X3];
3419 y3 = frags[SPAN_Y3];
caryclark1049f122015-04-20 08:31:59 -07003420 w = frags[SPAN_K_W];
caryclark55888e42016-07-18 10:01:36 -07003421 drawConicWithQuads(x1, y1, x2, y2, x3, y3, w);
caryclark1049f122015-04-20 08:31:59 -07003422 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003423 drawConicID(frags[0], x1, y1, x2, y2, x3, y3, w);
3424 }
3425 if (pt_labels) {
3426 var curve = [x1, y1, x2, y2, x3, y3, w];
3427 ctx.fillStyle = "blue";
3428 drawPoints(curve, PATH_CONIC, pt_labels == 2);
caryclark1049f122015-04-20 08:31:59 -07003429 }
3430 break;
caryclarkdac1d172014-06-17 05:15:38 -07003431 case ACTIVE_CUBIC_SPAN:
3432 x3 = frags[SPAN_X3];
3433 y3 = frags[SPAN_Y3];
3434 x4 = frags[SPAN_X4];
3435 y4 = frags[SPAN_Y4];
caryclark55888e42016-07-18 10:01:36 -07003436 drawCubic(x1, y1, x2, y2, x3, y3, x4, y4);
caryclarkdac1d172014-06-17 05:15:38 -07003437 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003438 drawCubicID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4);
3439 }
3440 if (pt_labels) {
3441 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
3442 ctx.fillStyle = "blue";
3443 drawPoints(curve, PATH_CUBIC, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003444 }
3445 break;
3446 default:
3447 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
3448 throw "stop execution";
3449 }
3450 break;
3451 case REC_TYPE_ACTIVE_OP:
3452 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
3453 continue;
3454 }
3455 focus_enabled = true;
3456 ctx.lineWidth = 3;
3457 var activeSpan = frags[7] == "1";
3458 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
3459 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3460 drawCurve(curve);
3461 if (draw_op > 1) {
3462 drawArc(curve, false, frags[3], frags[4]);
3463 drawArc(curve, true, frags[5], frags[6]);
3464 }
3465 break;
3466 case REC_TYPE_ADD:
3467 if (!draw_add) {
3468 continue;
3469 }
3470 ctx.lineWidth = 3;
3471 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
3472 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
3473 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
3474 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
3475 : "rgba(127,0,127, 0.3)";
3476 focus_enabled = true;
3477 switch (fragType) {
3478 case ADD_MOVETO:
3479 break;
3480 case ADD_LINETO:
3481 if (step_limit == 0 || tIndex >= lastAdd) {
3482 drawLine(frags[0], frags[1], frags[2], frags[3]);
3483 }
3484 break;
3485 case ADD_QUADTO:
3486 if (step_limit == 0 || tIndex >= lastAdd) {
3487 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
3488 }
3489 break;
caryclark1049f122015-04-20 08:31:59 -07003490 case ADD_CONICTO:
3491 if (step_limit == 0 || tIndex >= lastAdd) {
3492 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3493 frags[4], frags[5], frags[6]);
3494 }
3495 break;
caryclarkdac1d172014-06-17 05:15:38 -07003496 case ADD_CUBICTO:
3497 if (step_limit == 0 || tIndex >= lastAdd) {
3498 drawCubic(frags[0], frags[1], frags[2], frags[3],
3499 frags[4], frags[5], frags[6], frags[7]);
3500 }
3501 break;
3502 case ADD_CLOSE:
3503 ++closeCount;
3504 break;
3505 case ADD_FILL:
3506 break;
3507 default:
3508 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
3509 throw "stop execution";
3510 }
3511 break;
3512 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07003513 angleBetween = frags[18] == "T";
3514 afterIndex = 0;
3515 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07003516 continue;
3517 }
3518 focus_enabled = true;
3519 ctx.lineWidth = 3;
3520 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07003521 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
3522 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
3523 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07003524 drawCurve(leftCurve);
3525 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07003526 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07003527 drawCurve(midCurve);
3528 if (draw_angle > 1) {
Cary Clarkff114282016-12-14 11:56:16 -05003529 drawVisibleOrder(leftCurve, 'L');
3530 drawVisibleOrder(rightCurve, 'R');
3531 }
Ben Wagner29380bd2017-10-09 14:43:00 -04003532 if (draw_id) {
3533 drawVisibleID(leftCurve, 0.5, frags[0]);
3534 drawVisibleID(midCurve, 0.5, frags[6]);
3535 drawVisibleID(rightCurve, 0.5, frags[12]);
caryclarkdac1d172014-06-17 05:15:38 -07003536 }
3537 break;
caryclark54359292015-03-26 07:52:43 -07003538 case REC_TYPE_AFTERPART:
3539 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
3540 continue;
3541 }
3542 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
3543 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
Cary Clarkff114282016-12-14 11:56:16 -05003544 : "rgba(0,0,255, 1.0)";
3545 var curve;
3546 var id;
caryclark54359292015-03-26 07:52:43 -07003547 switch (fragType) {
3548 case PATH_LINE:
Cary Clarkff114282016-12-14 11:56:16 -05003549 curve = [ frags[0], frags[1], frags[2], frags[3] ];
3550 id = frags[4];
caryclark54359292015-03-26 07:52:43 -07003551 break;
3552 case PATH_QUAD:
Cary Clarkff114282016-12-14 11:56:16 -05003553 curve = [ frags[0], frags[1], frags[2], frags[3],
3554 frags[4], frags[5] ];
3555 id = frags[6];
caryclark54359292015-03-26 07:52:43 -07003556 break;
caryclark1049f122015-04-20 08:31:59 -07003557 case PATH_CONIC:
Cary Clarkff114282016-12-14 11:56:16 -05003558 curve = [ frags[0], frags[1], frags[2], frags[3],
3559 frags[4], frags[5], frags[6] ];
3560 id = frags[7];
caryclark1049f122015-04-20 08:31:59 -07003561 break;
caryclark54359292015-03-26 07:52:43 -07003562 case PATH_CUBIC:
Cary Clarkff114282016-12-14 11:56:16 -05003563 curve = [ frags[0], frags[1], frags[2], frags[3],
3564 frags[4], frags[5], frags[6], frags[7] ];
3565 id = frags[8];
caryclark54359292015-03-26 07:52:43 -07003566 break;
3567 default:
3568 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
3569 throw "stop execution";
3570 }
Cary Clarkff114282016-12-14 11:56:16 -05003571 drawCurve(curve);
Ben Wagner29380bd2017-10-09 14:43:00 -04003572 if (draw_id) {
3573 drawVisibleID(curve, 0.5, id);
Cary Clarkff114282016-12-14 11:56:16 -05003574 }
caryclark54359292015-03-26 07:52:43 -07003575 ++afterIndex;
3576 break;
caryclark624637c2015-05-11 07:21:27 -07003577 case REC_TYPE_COINCIDENCE:
3578 if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) {
3579 continue;
3580 }
3581 focus_enabled = true;
3582 ctx.lineWidth = 3;
3583 ctx.strokeStyle = "rgba(127,45,63, 0.3)";
3584 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3585 drawCurve(curve);
3586 break;
caryclarkdac1d172014-06-17 05:15:38 -07003587 case REC_TYPE_SECT:
3588 if (!draw_intersection) {
3589 continue;
3590 }
3591 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
3592 continue;
3593 }
3594 // draw_intersection == 1 : show all
3595 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
3596 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
3597 ctx.lineWidth = 1;
3598 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3599 ctx.fillStyle = "blue";
3600 focus_enabled = true;
3601 var f = [];
3602 var c1s;
3603 var c1l;
3604 var c2s;
3605 var c2l;
3606 switch (fragType) {
3607 case INTERSECT_LINE:
3608 f.push(5, 6, 0, 7);
3609 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
3610 break;
3611 case INTERSECT_LINE_2:
3612 f.push(5, 6, 0, 10);
3613 f.push(8, 9, 7, 15);
3614 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
3615 break;
3616 case INTERSECT_LINE_NO:
3617 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
3618 break;
3619 case INTERSECT_QUAD_LINE:
3620 f.push(7, 8, 0, 9);
3621 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
3622 break;
3623 case INTERSECT_QUAD_LINE_2:
3624 f.push(7, 8, 0, 12);
3625 f.push(10, 11, 9, 17);
3626 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
3627 break;
3628 case INTERSECT_QUAD_LINE_NO:
3629 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
3630 break;
3631 case INTERSECT_QUAD:
3632 f.push(7, 8, 0, 9);
3633 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
3634 break;
3635 case INTERSECT_QUAD_2:
3636 f.push(7, 8, 0, 12);
3637 f.push(10, 11, 9, 19);
3638 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
3639 break;
3640 case INTERSECT_QUAD_NO:
3641 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
3642 break;
caryclark1049f122015-04-20 08:31:59 -07003643 case INTERSECT_CONIC_LINE:
3644 f.push(8, 9, 0, 10);
3645 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
3646 break;
3647 case INTERSECT_CONIC_LINE_2:
3648 f.push(8, 9, 0, 12);
3649 f.push(11, 12, 10, 18);
3650 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
3651 break;
3652 case INTERSECT_CONIC_LINE_NO:
3653 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
3654 break;
caryclark55888e42016-07-18 10:01:36 -07003655 case INTERSECT_CONIC_QUAD:
3656 f.push(8, 9, 0, 10);
3657 c1s = 1; c1l = 7; c2s = 11; c2l = 6;
3658 break;
3659 case INTERSECT_CONIC_QUAD_2:
3660 f.push(8, 9, 0, 12);
3661 f.push(11, 12, 10, 18);
3662 c1s = 1; c1l = 7; c2s = 14; c2l = 6;
3663 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003664 case INTERSECT_CONIC_QUAD_3:
3665 f.push(8, 9, 0, 15);
3666 f.push(11, 12, 10, 21);
3667 f.push(14, 15, 13, 22);
3668 c1s = 1; c1l = 7; c2s = 17; c2l = 6;
3669 break;
3670 case INTERSECT_CONIC_QUAD_4:
3671 f.push(8, 9, 0, 18);
3672 f.push(11, 12, 10, 24);
3673 f.push(14, 15, 13, 25);
3674 f.push(17, 18, 16, 26);
3675 c1s = 1; c1l = 7; c2s = 20; c2l = 6;
3676 break;
caryclark55888e42016-07-18 10:01:36 -07003677 case INTERSECT_CONIC_QUAD_NO:
3678 c1s = 0; c1l = 7; c2s = 7; c2l = 6;
3679 break;
caryclark1049f122015-04-20 08:31:59 -07003680 case INTERSECT_CONIC:
3681 f.push(8, 9, 0, 10);
3682 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
3683 break;
3684 case INTERSECT_CONIC_2:
3685 f.push(8, 9, 0, 13);
3686 f.push(11, 12, 10, 21);
3687 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
3688 break;
3689 case INTERSECT_CONIC_NO:
3690 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
3691 break;
caryclarkdac1d172014-06-17 05:15:38 -07003692 case INTERSECT_SELF_CUBIC:
3693 f.push(9, 10, 0, 11);
3694 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
3695 break;
3696 case INTERSECT_SELF_CUBIC_NO:
3697 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
3698 break;
3699 case INTERSECT_CUBIC_LINE:
3700 f.push(9, 10, 0, 11);
3701 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3702 break;
3703 case INTERSECT_CUBIC_LINE_2:
3704 f.push(9, 10, 0, 14);
3705 f.push(12, 13, 11, 19);
3706 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3707 break;
3708 case INTERSECT_CUBIC_LINE_3:
3709 f.push(9, 10, 0, 17);
3710 f.push(12, 13, 11, 22);
3711 f.push(15, 16, 14, 23);
3712 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3713 break;
3714 case INTERSECT_CUBIC_QUAD_NO:
3715 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3716 break;
3717 case INTERSECT_CUBIC_QUAD:
3718 f.push(9, 10, 0, 11);
3719 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3720 break;
3721 case INTERSECT_CUBIC_QUAD_2:
3722 f.push(9, 10, 0, 14);
3723 f.push(12, 13, 11, 21);
3724 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3725 break;
3726 case INTERSECT_CUBIC_QUAD_3:
3727 f.push(9, 10, 0, 17);
3728 f.push(12, 13, 11, 24);
3729 f.push(15, 16, 14, 25);
3730 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3731 break;
3732 case INTERSECT_CUBIC_QUAD_4:
3733 f.push(9, 10, 0, 20);
3734 f.push(12, 13, 11, 27);
3735 f.push(15, 16, 14, 28);
3736 f.push(18, 19, 17, 29);
3737 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3738 break;
3739 case INTERSECT_CUBIC_LINE_NO:
3740 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3741 break;
3742 case INTERSECT_CUBIC:
3743 f.push(9, 10, 0, 11);
3744 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3745 break;
3746 case INTERSECT_CUBIC_2:
3747 f.push(9, 10, 0, 14);
3748 f.push(12, 13, 11, 23);
3749 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3750 break;
3751 case INTERSECT_CUBIC_3:
3752 f.push(9, 10, 0, 17);
3753 f.push(12, 13, 11, 26);
3754 f.push(15, 16, 14, 27);
3755 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3756 break;
3757 case INTERSECT_CUBIC_4:
3758 f.push(9, 10, 0, 20);
3759 f.push(12, 13, 11, 29);
3760 f.push(15, 16, 14, 30);
3761 f.push(18, 19, 17, 31);
3762 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3763 break;
3764 case INTERSECT_CUBIC_NO:
3765 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3766 break;
3767 default:
3768 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3769 throw "stop execution";
3770 }
3771 if (draw_intersection != 1) {
3772 var id = -1;
3773 var curve;
3774 switch (c1l) {
caryclark55888e42016-07-18 10:01:36 -07003775 case 4:
caryclarkdac1d172014-06-17 05:15:38 -07003776 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3777 if (draw_id) {
3778 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3779 id = idByCurve(test, curve, PATH_LINE);
3780 }
3781 break;
3782 case 6:
3783 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3784 frags[c1s + 4], frags[c1s + 5]);
3785 if (draw_id) {
3786 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3787 frags[c1s + 4], frags[c1s + 5]];
3788 id = idByCurve(test, curve, PATH_QUAD);
3789 }
3790 break;
caryclark1049f122015-04-20 08:31:59 -07003791 case 7:
3792 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3793 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3794 if (draw_id) {
3795 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3796 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3797 id = idByCurve(test, curve, PATH_CONIC);
3798 }
3799 break;
caryclarkdac1d172014-06-17 05:15:38 -07003800 case 8:
3801 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3802 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3803 if (draw_id) {
3804 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3805 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3806 id = idByCurve(test, curve, PATH_CUBIC);
3807 }
3808 break;
3809 }
3810 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05003811 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07003812 }
3813 id = -1;
3814 switch (c2l) {
3815 case 0:
3816 break;
caryclark55888e42016-07-18 10:01:36 -07003817 case 4:
caryclarkdac1d172014-06-17 05:15:38 -07003818 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3819 if (draw_id) {
3820 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3821 id = idByCurve(test, curve, PATH_LINE);
3822 }
3823 break;
3824 case 6:
3825 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3826 frags[c2s + 4], frags[c2s + 5]);
3827 if (draw_id) {
3828 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3829 frags[c2s + 4], frags[c2s + 5]];
3830 id = idByCurve(test, curve, PATH_QUAD);
3831 }
3832 break;
caryclark1049f122015-04-20 08:31:59 -07003833 case 7:
3834 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3835 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3836 if (draw_id) {
3837 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3838 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3839 id = idByCurve(test, curve, PATH_CONIC);
3840 }
3841 break;
caryclarkdac1d172014-06-17 05:15:38 -07003842 case 8:
3843 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3844 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3845 if (draw_id) {
3846 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3847 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3848 id = idByCurve(test, curve, PATH_CUBIC);
3849 }
3850 break;
3851 }
3852 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05003853 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07003854 }
3855 }
3856 if (collect_bounds) {
3857 break;
3858 }
caryclark54359292015-03-26 07:52:43 -07003859 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3860 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003861 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3862 }
3863 }
3864 if (!draw_intersectT) {
3865 break;
3866 }
3867 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003868 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3869 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003870 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3871 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3872 }
3873 }
3874 break;
3875 case REC_TYPE_SORT:
3876 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3877 continue;
3878 }
3879 ctx.lineWidth = 3;
3880 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3881 focus_enabled = true;
3882 switch (fragType) {
3883 case SORT_UNARY:
3884 case SORT_BINARY:
3885 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3886 drawCurve(curve);
3887 break;
3888 default:
3889 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3890 throw "stop execution";
3891 }
3892 break;
caryclark03b03ca2015-04-23 09:13:37 -07003893 case REC_TYPE_TOP:
3894 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
3895 continue;
3896 }
3897 ctx.lineWidth = 3;
3898 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3899 focus_enabled = true;
3900 {
3901 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3902 drawCurve(curve);
3903 var type = PATH_LINE + (curve.length / 2 - 2);
3904 var mid = pointAtT(curve, type, 0.5);
3905 var d = dxy_at_t(curve, type, 0.5);
3906 drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
3907 }
3908 break;
caryclarkdac1d172014-06-17 05:15:38 -07003909 case REC_TYPE_MARK:
3910 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3911 continue;
3912 }
3913 ctx.lineWidth = 3;
3914 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3915 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3916 focus_enabled = true;
3917 switch (fragType) {
3918 case MARK_LINE:
3919 case MARK_DONE_LINE:
3920 case MARK_UNSORTABLE_LINE:
3921 case MARK_SIMPLE_LINE:
3922 case MARK_SIMPLE_DONE_LINE:
3923 case MARK_DONE_UNARY_LINE:
3924 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3925 frags[5], frags[9]);
3926 if (draw_id) {
3927 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3928 frags[5], frags[9]);
3929 }
3930 break;
3931 case MARK_QUAD:
3932 case MARK_DONE_QUAD:
3933 case MARK_UNSORTABLE_QUAD:
3934 case MARK_SIMPLE_QUAD:
3935 case MARK_SIMPLE_DONE_QUAD:
3936 case MARK_DONE_UNARY_QUAD:
3937 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3938 frags[5], frags[6], frags[7], frags[11]);
3939 if (draw_id) {
3940 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3941 frags[5], frags[6], frags[7], frags[11]);
3942 }
3943 break;
3944 case MARK_CUBIC:
3945 case MARK_DONE_CUBIC:
3946 case MARK_UNSORTABLE_CUBIC:
3947 case MARK_SIMPLE_CUBIC:
3948 case MARK_SIMPLE_DONE_CUBIC:
3949 case MARK_DONE_UNARY_CUBIC:
3950 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3951 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3952 if (draw_id) {
3953 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3954 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3955 }
3956 break;
3957 case MARK_ANGLE_LAST:
3958 // FIXME: ignored for now
3959 break;
3960 default:
3961 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3962 throw "stop execution";
3963 }
3964 break;
3965 default:
3966 continue;
3967 }
3968 }
3969 switch (recType) {
3970 case REC_TYPE_SORT:
3971 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3972 break;
3973 }
3974 var angles = []; // use tangent lines to describe arcs
3975 var windFrom = [];
3976 var windTo = [];
3977 var opp = [];
3978 var minXY = Number.MAX_VALUE;
3979 var partial;
3980 focus_enabled = true;
3981 var someUnsortable = false;
3982 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3983 var fragType = records[recordIndex];
3984 var frags = records[recordIndex + 1];
3985 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3986 (fragType == SORT_BINARY && frags[16]);
3987 someUnsortable |= unsortable;
3988 switch (fragType) {
3989 case SORT_UNARY:
3990 case SORT_BINARY:
3991 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3992 break;
3993 default:
3994 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3995 throw "stop execution";
3996 }
3997 var dx = boundsWidth(partial);
3998 var dy = boundsHeight(partial);
3999 minXY = Math.min(minXY, dx * dx + dy * dy);
4000 if (collect_bounds) {
4001 continue;
4002 }
4003 angles.push(tangent(partial));
4004 var from = frags[12];
4005 var to = frags[12];
4006 var sgn = frags[10];
4007 if (sgn < 0) {
4008 from -= frags[11];
4009 } else if (sgn > 0) {
4010 to -= frags[11];
4011 }
4012 windFrom.push(from + (unsortable ? "!" : ""));
4013 windTo.push(to + (unsortable ? "!" : ""));
4014 opp.push(fragType == SORT_BINARY);
4015 if (draw_sort == 1) {
Cary Clarkff114282016-12-14 11:56:16 -05004016 drawVisibleOrder(partial, frags[12]);
caryclarkdac1d172014-06-17 05:15:38 -07004017 } else {
Cary Clarkff114282016-12-14 11:56:16 -05004018 drawVisibleOrder(partial, (recordIndex / 2) + 1);
caryclarkdac1d172014-06-17 05:15:38 -07004019 }
4020 }
4021 var radius = Math.sqrt(minXY) / 2 * scale;
4022 radius = Math.min(50, radius);
4023 var scaledRadius = radius / scale;
4024 var centerX = partial[0];
4025 var centerY = partial[1];
4026 if (collect_bounds) {
4027 if (focus_enabled) {
4028 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
4029 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
4030 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
4031 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
4032 }
4033 break;
4034 }
4035 break;
4036 default:
4037 break;
4038 }
4039 }
4040 if (collect_bounds) {
4041 return;
4042 }
4043 if (draw_log && logStart >= 0) {
4044 ctx.font = "normal 10px Arial";
4045 ctx.textAlign = "left";
4046 ctx.beginPath();
4047 var top = screenHeight - 20 - (logRange + 2) * 10;
4048 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
4049 ctx.fillStyle = "white";
4050 ctx.fill();
4051 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4052 if (logStart > 0) {
4053 ctx.fillText(lines[logStart - 1], 50, top + 8);
4054 }
4055 ctx.fillStyle = "black";
4056 for (var idx = 0; idx < logRange; ++idx) {
4057 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
4058 }
4059 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4060 if (logStart + logRange < lines.length) {
4061 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
4062 }
4063 }
4064 if (draw_legend) {
4065 var pos = 0;
caryclark624637c2015-05-11 07:21:27 -07004066 var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07004067 // drawBox(pos++, "yellow", "black", opLetter, true, '');
4068 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
4069 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
4070 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
4071 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
caryclark624637c2015-05-11 07:21:27 -07004072 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey);
caryclarkdac1d172014-06-17 05:15:38 -07004073 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
4074 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
caryclark03b03ca2015-04-23 09:13:37 -07004075 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
caryclarkdac1d172014-06-17 05:15:38 -07004076 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
caryclark55888e42016-07-18 10:01:36 -07004077 drawBox(pos++, "black", "white",
caryclark26ad22a2015-10-16 09:03:38 -07004078 (new Array('P', 'P1', 'P2', 'P', 'p', 'p1', 'p2'))[draw_path], draw_path != 0, pathKey);
caryclarkdac1d172014-06-17 05:15:38 -07004079 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
4080 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
4081 draw_computed != 0, computedKey);
4082 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
4083 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
4084 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
4085 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
4086 if (curve_t) {
4087 drawCurveTControl();
4088 }
4089 ctx.font = "normal 20px Arial";
4090 ctx.fillStyle = "rgba(0,0,0, 0.3)";
4091 ctx.textAlign = "right";
4092 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
4093 }
4094 if (draw_hints) {
4095 ctx.font = "normal 10px Arial";
4096 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4097 ctx.textAlign = "right";
4098 var y = 4;
4099 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
4100 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
4101 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
4102 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07004103 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
4104 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
4105 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
4106 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
4107 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
4108 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
4109 }
4110}
4111
4112function drawBox(y, backC, foreC, str, enable, label) {
4113 ctx.beginPath();
4114 ctx.fillStyle = backC;
4115 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
4116 ctx.fill();
4117 ctx.font = "normal 16px Arial";
4118 ctx.fillStyle = foreC;
4119 ctx.textAlign = "center";
4120 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
4121 if (!enable) {
4122 ctx.fillStyle = "rgba(255,255,255, 0.5)";
4123 ctx.fill();
4124 }
4125 if (label != '') {
4126 ctx.font = "normal 9px Arial";
4127 ctx.fillStyle = "black";
4128 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
4129 }
4130}
4131
4132function drawCurveTControl() {
4133 ctx.lineWidth = 2;
4134 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
4135 ctx.beginPath();
4136 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
4137 ctx.stroke();
4138 var ty = 40 + curveT * (screenHeight - 80);
4139 ctx.beginPath();
4140 ctx.moveTo(screenWidth - 80, ty);
4141 ctx.lineTo(screenWidth - 85, ty - 5);
4142 ctx.lineTo(screenWidth - 85, ty + 5);
4143 ctx.lineTo(screenWidth - 80, ty);
4144 ctx.fillStyle = "rgba(0,0,0, 0.6)";
4145 ctx.fill();
4146 var num = curveT.toFixed(decimal_places);
4147 ctx.font = "normal 10px Arial";
4148 ctx.textAlign = "left";
4149 ctx.fillText(num, screenWidth - 78, ty);
4150}
4151
4152function ptInTControl() {
4153 var e = window.event;
caryclark55888e42016-07-18 10:01:36 -07004154 var tgt = e.target || e.srcElement;
caryclarkdac1d172014-06-17 05:15:38 -07004155 var left = tgt.offsetLeft;
4156 var top = tgt.offsetTop;
4157 var x = (e.clientX - left);
4158 var y = (e.clientY - top);
4159 if (x < screenWidth - 80 || x > screenWidth - 50) {
4160 return false;
4161 }
4162 if (y < 40 || y > screenHeight - 80) {
4163 return false;
4164 }
4165 curveT = (y - 40) / (screenHeight - 120);
4166 if (curveT < 0 || curveT > 1) {
4167 throw "stop execution";
4168 }
4169 return true;
4170}
4171
4172function drawTop() {
4173 if (tests[testIndex] == null) {
4174 var str = testDivs[testIndex].textContent;
4175 parse_all(str);
4176 var title = testDivs[testIndex].id.toString();
4177 testTitles[testIndex] = title;
4178 }
4179 init(tests[testIndex]);
4180 redraw();
4181}
4182
4183function redraw() {
4184 if (focus_on_selection) {
4185 collect_bounds = true;
4186 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
4187 collect_bounds = false;
4188 if (focusXmin < focusXmax && focusYmin < focusYmax) {
4189 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
4190 }
4191 }
4192 ctx.beginPath();
4193 ctx.fillStyle = "white";
4194 ctx.rect(0, 0, screenWidth, screenHeight);
4195 ctx.fill();
4196 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
4197}
4198
4199function dumpCurvePartial(test, id, t0, t1) {
4200 var curve = curveByID(test, id);
4201 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
4202 console.log("id=" + id + " " + name + "=" + curveToString(curve)
4203 + " t0=" + t0 + " t1=" + t1
4204 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
4205}
4206
4207function dumpAngleTest(test, id, t0, t1) {
4208 var curve = curveByID(test, id);
caryclark55888e42016-07-18 10:01:36 -07004209 console.log(" { {" + curveToString(curve) + "}, "
caryclarkdac1d172014-06-17 05:15:38 -07004210 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
4211}
4212
4213function dumpLogToConsole() {
4214 if (logStart < 0) {
4215 return;
4216 }
4217 var test = tests[testIndex];
4218 var recType = REC_TYPE_UNKNOWN;
4219 var records;
4220 for (var index = 0; index < test.length; index += 3) {
4221 var lastLineNo = test[index + 1];
4222 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
4223 recType = test[index];
4224 records = test[index + 2];
4225 break;
4226 }
4227 }
4228 if (recType == REC_TYPE_UNKNOWN) {
4229 return;
4230 }
4231 var lines = testLines[testIndex];
4232 for (var idx = 0; idx < logRange; ++idx) {
4233 var line = lines[logStart + idx];
4234 console.log(line);
4235 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
4236 var fragType = records[recordIndex];
4237 var frags = records[recordIndex + 1];
4238 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07004239 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
4240 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
4241 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
4242 console.log("\nstatic IntersectData intersectDataSet[] = { //");
4243 dumpAngleTest(test, frags[0], frags[4], frags[5]);
4244 dumpAngleTest(test, frags[6], frags[10], frags[11]);
4245 dumpAngleTest(test, frags[12], frags[16], frags[17]);
4246 console.log("}; //");
4247 }
4248 }
4249 }
4250}
4251
4252var activeKey = 'a';
4253var pathKey = 'b';
4254var pathBackKey = 'B';
4255var centerKey = 'c';
caryclark624637c2015-05-11 07:21:27 -07004256var coincidenceKey = 'C';
caryclarkdac1d172014-06-17 05:15:38 -07004257var addKey = 'd';
4258var deriviativesKey = 'f';
4259var angleKey = 'g';
4260var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07004261var intersectionKey = 'i';
4262var intersectionBackKey = 'I';
4263var sequenceKey = 'j';
4264var midpointKey = 'k';
4265var logKey = 'l';
4266var logToConsoleKey = 'L';
4267var markKey = 'm';
4268var sortKey = 'o';
4269var opKey = 'p';
4270var opBackKey = 'P';
4271var computedKey = 'q';
4272var computedBackKey = 'Q';
Cary Clarkff114282016-12-14 11:56:16 -05004273var directionKey = 'r';
caryclarkdac1d172014-06-17 05:15:38 -07004274var stepKey = 's';
4275var stepBackKey = 'S';
4276var intersectTKey = 't';
caryclark03b03ca2015-04-23 09:13:37 -07004277var topKey = 'T';
caryclarkdac1d172014-06-17 05:15:38 -07004278var curveTKey = 'u';
4279var controlLinesBackKey = 'V';
4280var controlLinesKey = 'v';
4281var ptsKey = 'x';
4282var xyKey = 'y';
4283var logCurvesKey = 'z';
4284var focusKey = '`';
4285var idKey = '.';
4286var retinaKey = '\\';
4287
4288function doKeyPress(evt) {
4289 var char = String.fromCharCode(evt.charCode);
4290 var focusWasOn = false;
4291 switch (char) {
4292 case '0':
4293 case '1':
4294 case '2':
4295 case '3':
4296 case '4':
4297 case '5':
4298 case '6':
4299 case '7':
4300 case '8':
4301 case '9':
4302 decimal_places = char - '0';
4303 redraw();
4304 break;
4305 case activeKey:
4306 draw_active ^= true;
caryclark55888e42016-07-18 10:01:36 -07004307 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004308 break;
4309 case addKey:
4310 draw_add ^= true;
caryclark55888e42016-07-18 10:01:36 -07004311 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004312 break;
4313 case angleKey:
caryclark54359292015-03-26 07:52:43 -07004314 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07004315 redraw();
4316 break;
4317 case angleBackKey:
4318 draw_angle = (draw_angle + 2) % 3;
4319 redraw();
4320 break;
4321 case centerKey:
4322 setScale(xmin, xmax, ymin, ymax);
caryclark55888e42016-07-18 10:01:36 -07004323 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004324 break;
caryclark624637c2015-05-11 07:21:27 -07004325 case coincidenceKey:
4326 draw_coincidence ^= true;
4327 redraw();
4328 break;
caryclarkdac1d172014-06-17 05:15:38 -07004329 case controlLinesBackKey:
4330 control_lines = (control_lines + 3) % 4;
caryclark55888e42016-07-18 10:01:36 -07004331 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004332 break;
4333 case controlLinesKey:
4334 control_lines = (control_lines + 1) % 4;
caryclark55888e42016-07-18 10:01:36 -07004335 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004336 break;
4337 case computedBackKey:
4338 draw_computed = (draw_computed + 5) % 6;
caryclark55888e42016-07-18 10:01:36 -07004339 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004340 break;
4341 case computedKey:
4342 draw_computed = (draw_computed + 1) % 6;
caryclark55888e42016-07-18 10:01:36 -07004343 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004344 break;
4345 case curveTKey:
4346 curve_t ^= true;
4347 if (curve_t) {
4348 draw_legend = true;
4349 }
4350 redraw();
4351 break;
4352 case deriviativesKey:
4353 draw_deriviatives = (draw_deriviatives + 1) % 3;
4354 redraw();
4355 break;
Cary Clarkff114282016-12-14 11:56:16 -05004356 case directionKey:
4357 draw_direction ^= true;
4358 redraw();
4359 break;
caryclarkdac1d172014-06-17 05:15:38 -07004360 case focusKey:
4361 focus_on_selection ^= true;
4362 setScale(xmin, xmax, ymin, ymax);
4363 redraw();
4364 break;
caryclarkdac1d172014-06-17 05:15:38 -07004365 case idKey:
4366 draw_id ^= true;
4367 redraw();
4368 break;
4369 case intersectionBackKey:
4370 draw_intersection = (draw_intersection + 3) % 4;
caryclark55888e42016-07-18 10:01:36 -07004371 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004372 break;
4373 case intersectionKey:
4374 draw_intersection = (draw_intersection + 1) % 4;
caryclark55888e42016-07-18 10:01:36 -07004375 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004376 break;
4377 case intersectTKey:
4378 draw_intersectT ^= true;
4379 redraw();
4380 break;
4381 case logCurvesKey:
4382 logCurves(tests[testIndex]);
4383 break;
4384 case logKey:
4385 draw_log ^= true;
4386 redraw();
4387 break;
4388 case logToConsoleKey:
4389 if (draw_log) {
4390 dumpLogToConsole();
4391 }
4392 break;
4393 case markKey:
4394 draw_mark ^= true;
4395 redraw();
4396 break;
4397 case midpointKey:
4398 draw_midpoint ^= true;
4399 redraw();
4400 break;
4401 case opKey:
4402 draw_op = (draw_op + 1) % 3;
4403 redraw();
4404 break;
4405 case opBackKey:
4406 draw_op = (draw_op + 2) % 3;
4407 redraw();
4408 break;
4409 case pathKey:
caryclark26ad22a2015-10-16 09:03:38 -07004410 draw_path = (draw_path + 1) % (4 + (hasAlignedPath ? 3 : 0));
caryclark55888e42016-07-18 10:01:36 -07004411 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004412 break;
4413 case pathBackKey:
caryclark26ad22a2015-10-16 09:03:38 -07004414 draw_path = (draw_path + 3 + (hasAlignedPath ? 3 : 0)) % (4 + (hasAlignedPath ? 3 : 0));
caryclark55888e42016-07-18 10:01:36 -07004415 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004416 break;
4417 case ptsKey:
4418 pt_labels = (pt_labels + 1) % 3;
4419 redraw();
4420 break;
4421 case retinaKey:
4422 retina_scale ^= true;
4423 drawTop();
4424 break;
4425 case sequenceKey:
4426 draw_sequence ^= true;
4427 redraw();
4428 break;
4429 case sortKey:
4430 draw_sort = (draw_sort + 1) % 3;
4431 drawTop();
4432 break;
4433 case stepKey:
4434 step_limit++;
4435 if (step_limit > stepMax) {
4436 step_limit = stepMax;
4437 }
4438 redraw();
4439 break;
4440 case stepBackKey:
4441 step_limit--;
4442 if (step_limit < 0) {
4443 step_limit = 0;
4444 }
4445 redraw();
4446 break;
caryclark03b03ca2015-04-23 09:13:37 -07004447 case topKey:
4448 draw_top ^= true;
4449 redraw();
4450 break;
caryclarkdac1d172014-06-17 05:15:38 -07004451 case xyKey:
4452 debug_xy = (debug_xy + 1) % 3;
4453 redraw();
4454 break;
4455 case '-':
4456 focusWasOn = focus_on_selection;
4457 if (focusWasOn) {
4458 focus_on_selection = false;
4459 scale /= 1.2;
4460 } else {
4461 scale /= 2;
4462 calcLeftTop();
4463 }
4464 redraw();
4465 focus_on_selection = focusWasOn;
4466 break;
4467 case '=':
4468 case '+':
4469 focusWasOn = focus_on_selection;
4470 if (focusWasOn) {
4471 focus_on_selection = false;
4472 scale *= 1.2;
4473 } else {
4474 scale *= 2;
4475 calcLeftTop();
4476 }
4477 redraw();
4478 focus_on_selection = focusWasOn;
4479 break;
4480 case '?':
4481 draw_hints ^= true;
4482 if (draw_hints && !draw_legend) {
4483 draw_legend = true;
4484 }
4485 redraw();
4486 break;
4487 case '/':
4488 draw_legend ^= true;
4489 redraw();
4490 break;
4491 }
4492}
4493
4494function doKeyDown(evt) {
4495 var char = evt.keyCode;
4496 var preventDefault = false;
4497 switch (char) {
4498 case 37: // left arrow
4499 if (evt.shiftKey) {
4500 testIndex -= 9;
4501 }
4502 if (--testIndex < 0)
4503 testIndex = tests.length - 1;
4504 drawTop();
4505 preventDefault = true;
4506 break;
4507 case 39: // right arrow
4508 if (evt.shiftKey) {
4509 testIndex += 9;
4510 }
4511 if (++testIndex >= tests.length)
4512 testIndex = 0;
4513 drawTop();
4514 preventDefault = true;
4515 break;
4516 }
4517 if (preventDefault) {
4518 evt.preventDefault();
4519 return false;
4520 }
4521 return true;
4522}
4523
4524(function() {
4525 var hidden = "hidden";
4526
4527 // Standards:
4528 if (hidden in document)
4529 document.addEventListener("visibilitychange", onchange);
4530 else if ((hidden = "mozHidden") in document)
4531 document.addEventListener("mozvisibilitychange", onchange);
4532 else if ((hidden = "webkitHidden") in document)
4533 document.addEventListener("webkitvisibilitychange", onchange);
4534 else if ((hidden = "msHidden") in document)
4535 document.addEventListener("msvisibilitychange", onchange);
4536 // IE 9 and lower:
4537 else if ('onfocusin' in document)
4538 document.onfocusin = document.onfocusout = onchange;
4539 // All others:
4540 else
caryclark55888e42016-07-18 10:01:36 -07004541 window.onpageshow = window.onpagehide
caryclarkdac1d172014-06-17 05:15:38 -07004542 = window.onfocus = window.onblur = onchange;
4543
4544 function onchange (evt) {
4545 var v = 'visible', h = 'hidden',
caryclark55888e42016-07-18 10:01:36 -07004546 evtMap = {
4547 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
caryclarkdac1d172014-06-17 05:15:38 -07004548 };
4549
4550 evt = evt || window.event;
4551 if (evt.type in evtMap)
4552 document.body.className = evtMap[evt.type];
caryclark55888e42016-07-18 10:01:36 -07004553 else
caryclarkdac1d172014-06-17 05:15:38 -07004554 document.body.className = this[hidden] ? "hidden" : "visible";
4555 }
4556})();
4557
4558function calcXY() {
4559 var e = window.event;
caryclark55888e42016-07-18 10:01:36 -07004560 var tgt = e.target || e.srcElement;
caryclarkdac1d172014-06-17 05:15:38 -07004561 var left = tgt.offsetLeft;
4562 var top = tgt.offsetTop;
4563 mouseX = (e.clientX - left) / scale + srcLeft;
4564 mouseY = (e.clientY - top) / scale + srcTop;
4565}
4566
4567function calcLeftTop() {
4568 srcLeft = mouseX - screenWidth / 2 / scale;
4569 srcTop = mouseY - screenHeight / 2 / scale;
4570}
4571
4572var disableClick = false;
4573
4574function handleMouseClick() {
4575 if (disableClick) {
4576 return;
4577 }
4578 if (!curve_t || !ptInTControl()) {
4579 calcXY();
4580 calcLeftTop();
4581 }
4582 redraw();
4583// if (!curve_t || !ptInTControl()) {
4584// mouseX = screenWidth / 2 / scale + srcLeft;
4585// mouseY = screenHeight / 2 / scale + srcTop;
4586// }
4587}
4588
4589function handleMouseOver() {
4590 calcXY();
4591 if (debug_xy != 2) {
4592 return;
4593 }
4594 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
4595 ctx.beginPath();
4596 ctx.rect(300,100,num.length * 6,10);
4597 ctx.fillStyle="white";
4598 ctx.fill();
4599 ctx.font = "normal 10px Arial";
4600 ctx.fillStyle="black";
4601 ctx.textAlign = "left";
4602 ctx.fillText(num, 300, 108);
4603}
4604
4605function start() {
4606 for (var i = 0; i < testDivs.length; ++i) {
4607 tests[i] = null;
4608 }
4609 testIndex = 0;
4610 drawTop();
4611 window.addEventListener('keypress', doKeyPress, true);
4612 window.addEventListener('keydown', doKeyDown, true);
4613 window.onresize = function() {
4614 drawTop();
4615 }
4616 /*
4617 window.onpagehide = function() {
4618 disableClick = true;
4619 }
4620 */
4621 window.onpageshow = function () {
4622 disableClick = false;
4623 }
4624}
4625
4626</script>
4627</head>
4628
4629<body onLoad="start();">
4630<canvas id="canvas" width="750" height="500"
4631 onmousemove="handleMouseOver()"
4632 onclick="handleMouseClick()"
4633 ></canvas >
4634</body>
4635</html>