skia2/tools/pathops_visualizer.htm

5124 lines
227 KiB
HTML
Raw Normal View History

<html>
<head>
<div height="0" hidden="true">
<div id="crbug_526025">
SkDCubic::ComplexBreak
{{{360, -2147483648}, {593011648, -2147483520}, {1073742208, -1666752896}, {1073742080, -1073741568}}},
maxCurvature[0]=0.500000161 {{{-406603233.5424470901, -2998846434.998814106}, {1925104612.000926018, -667136804.5425114632}}},
seg=1 {{{360, -2147483648}, {593011648, -2147483520}, {1073742208, -1666752896}, {1073742080, -1073741568}}}
seg=2 {{{1073742080, -1073741568}, {1073742080, -480730560}, {593011840, -135.508026f}, {905.953125f, 255.999786f}}}
seg=3 {{{905.953125f, 255.999786f}, {815.80835f, 897.304565f}}}
seg=4 {{{815.80835f, 897.304565f}, {213.229446f, 572.949036f}}}
seg=5 {{{213.229446f, 572.949036f}, {32, 16}}}
seg=6 {{{32, 16}, {100, 512}}}
seg=7 {{{100, 512}, {213.229446f, 572.949036f}}}
seg=8 {{{213.229446f, 572.949036f}, {360, 1024}}}
seg=9 {{{360, 1024}, {360, 4140}}}
seg=10 {{{360, 4140}, {360, -2147483648}}}
op union
seg=11 {{{127, 321}, {6840, 270}}}
seg=12 {{{6840, 270}, {-21474836480, 100000000}}}
seg=13 {{{-21474836480, 100000000}, {2551, 64}}}
seg=14 {{{2551, 64}, {127, 321}}}
debugShowCubicIntersection wtTs[0]=1 {{{360,-2.14748365e+09}, {593011648,-2.14748352e+09}, {1.07374221e+09,-1.6667529e+09}, {1.07374208e+09,-1.07374157e+09}}} {{1.07374208e+09,-1.07374157e+09}} wnTs[0]=0 {{{1.07374208e+09,-1.07374157e+09}, {1.07374208e+09,-480730560}, {593011840,-135.508026}, {905.953125,255.999786}}}
debugShowCubicLineIntersection wtTs[0]=0 {{{360,-2.14748365e+09}, {593011648,-2.14748352e+09}, {1.07374221e+09,-1.6667529e+09}, {1.07374208e+09,-1.07374157e+09}}} {{360,-2.14748365e+09}} wnTs[0]=1 {{{360,4140}, {360,-2.14748365e+09}}}
debugShowCubicLineIntersection wtTs[0]=1 {{{1.07374208e+09,-1.07374157e+09}, {1.07374208e+09,-480730560}, {593011840,-135.508026}, {905.953125,255.999786}}} {{905.953125,255.999786}} wnTs[0]=0 {{{905.953125,255.999786}, {815.80835,897.304565}}}
debugShowLineIntersection wtTs[0]=1 {{{905.953125,255.999786}, {815.80835,897.304565}}} {{815.80835,897.304565}} wnTs[0]=0 {{{815.80835,897.304565}, {213.229446,572.949036}}}
debugShowLineIntersection wtTs[0]=1 {{{815.80835,897.304565}, {213.229446,572.949036}}} {{213.229446,572.949036}} wnTs[0]=0 {{{213.229446,572.949036}, {32,16}}}
debugShowLineIntersection wtTs[0]=1 {{{815.80835,897.304565}, {213.229446,572.949036}}} {{213.229446,572.949036}} wnTs[0]=1 {{{100,512}, {213.229446,572.949036}}}
debugShowLineIntersection wtTs[0]=1 {{{815.80835,897.304565}, {213.229446,572.949036}}} {{213.229446,572.949036}} wnTs[0]=0 {{{213.229446,572.949036}, {360,1024}}}
debugShowLineIntersection wtTs[0]=0.756429319 {{{815.80835,897.304565}, {213.229446,572.949036}}} {{360,651.952515}} wnTs[0]=1.62425e-06 {{{360,4140}, {360,-2.14748365e+09}}}
SkOpSegment::addT insert t=0.756429319 segID=4 spanID=29
SkOpSegment::addT insert t=1.62424554e-06 segID=10 spanID=30
debugShowLineIntersection wtTs[0]=1 {{{213.229446,572.949036}, {32,16}}} {{32,16}} wnTs[0]=0 {{{32,16}, {100,512}}}
debugShowLineIntersection wtTs[0]=0 {{{213.229446,572.949036}, {32,16}}} {{213.229446,572.949036}} wnTs[0]=1 {{{100,512}, {213.229446,572.949036}}}
debugShowLineIntersection wtTs[0]=0 {{{213.229446,572.949036}, {32,16}}} {{213.229446,572.949036}} wnTs[0]=0 {{{213.229446,572.949036}, {360,1024}}}
debugShowLineIntersection wtTs[0]=1 {{{32,16}, {100,512}}} {{100,512}} wnTs[0]=0 {{{100,512}, {213.229446,572.949036}}}
debugShowLineIntersection wtTs[0]=1 {{{100,512}, {213.229446,572.949036}}} {{213.229446,572.949036}} wnTs[0]=0 {{{213.229446,572.949036}, {360,1024}}}
debugShowLineIntersection wtTs[0]=1 {{{213.229446,572.949036}, {360,1024}}} {{360,1024}} wnTs[0]=0 {{{360,1024}, {360,4140}}}
debugShowLineIntersection wtTs[0]=1 {{{213.229446,572.949036}, {360,1024}}} {{360,1024}} wnTs[0]=1.451e-06 {{{360,4140}, {360,-2.14748365e+09}}}
SkOpSegment::addT insert t=1.45099777e-06 segID=10 spanID=31
debugShowLineIntersection wtTs[0]=0 {{{360,4140}, {360,-2.14748365e+09}}} {{360,4140}} wtTs[1]=1.45099777e-06 {{360,1024}} wnTs[0]=1 {{{360,1024}, {360,4140}}} wnTs[1]=0
debugShowCubicLineIntersection wtTs[0]=1 {{{1.07374208e+09,-1.07374157e+09}, {1.07374208e+09,-480730560}, {593011840,-135.508026}, {905.953125,255.999786}}} {{905.953125,255.999786}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}}
SkOpSegment::addT insert t=0.999999923 segID=13 spanID=32
debugShowCubicLineIntersection no intersect {{{1.07374208e+09,-1.07374157e+09}, {1.07374208e+09,-480730560}, {593011840,-135.508026}, {905.953125,255.999786}}} {{{2551,64}, {127,321}}}
debugShowLineIntersection wtTs[0]=0.0922268392 {{{905.953125,255.999786}, {815.80835,897.304565}}} {{897.639343,315.145294}} wnTs[0]=0.114798 {{{127,321}, {6840,270}}}
SkOpSegment::addT insert t=0.0922268392 segID=3 spanID=33
SkOpSegment::addT insert t=0.114798057 segID=11 spanID=34
debugShowLineIntersection wtTs[0]=0.0649612467 {{{905.953125,255.999786}, {815.80835,897.304565}}} {{900.097229,297.65976}} wtTs[1]=1 {{815.80835,897.304565}} wnTs[0]=2.76598e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=2.80653133e-07
SkOpSegment::addT insert t=0.0649612467 segID=3 spanID=35
SkOpSegment::addT insert t=2.7659819e-07 segID=12 spanID=36
SkOpSegment::addT insert t=2.80653133e-07 segID=12 spanID=37
debugShowLineIntersection wtTs[0]=0 {{{905.953125,255.999786}, {815.80835,897.304565}}} {{905.953125,255.999786}} wtTs[1]=1 {{815.80835,897.304565}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} wnTs[1]=0.999999919
SkOpSegment::addT insert t=0.999999919 segID=13 spanID=38
debugShowLineIntersection no intersect {{{905.953125,255.999786}, {815.80835,897.304565}}} {{{2551,64}, {127,321}}}
debugShowLineIntersection wtTs[0]=0 {{{815.80835,897.304565}, {213.229446,572.949036}}} {{815.80835,897.304565}} wtTs[1]=1 {{213.229446,572.949036}} wnTs[0]=2.80653e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=3.08641951e-07
SkOpSegment::addT insert t=3.08641951e-07 segID=12 spanID=39
debugShowLineIntersection wtTs[0]=0 {{{815.80835,897.304565}, {213.229446,572.949036}}} {{815.80835,897.304565}} wtTs[1]=1 {{213.229446,572.949036}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} wnTs[1]=0.999999891
SkOpSegment::addT insert t=0.999999891 segID=13 spanID=40
debugShowLineIntersection wtTs[0]=0.452431368 {{{213.229446,572.949036}, {32,16}}} {{131.235565,320.967834}} wnTs[0]=0.000630949 {{{127,321}, {6840,270}}}
SkOpSegment::addT insert t=0.452431368 segID=5 spanID=41
SkOpSegment::addT insert t=0.000630948916 segID=11 spanID=42
debugShowLineIntersection wtTs[0]=0 {{{213.229446,572.949036}, {32,16}}} {{213.229446,572.949036}} wtTs[1]=0.487798966 {{124.825912,301.269867}} wnTs[0]=3.08642e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=3.12699562e-07
SkOpSegment::addT insert t=0.487798966 segID=5 spanID=43
SkOpSegment::addT insert t=3.12699562e-07 segID=12 spanID=44
debugShowLineIntersection wtTs[0]=0 {{{213.229446,572.949036}, {32,16}}} {{213.229446,572.949036}} wtTs[1]=0.892917257 {{51.4065475,75.6396332}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} wnTs[1]=0.999999884
SkOpSegment::addT insert t=0.892917257 segID=5 spanID=45
SkOpSegment::addT insert t=0.999999884 segID=13 spanID=46
debugShowLineIntersection wtTs[0]=0.453154928 {{{213.229446,572.949036}, {32,16}}} {{131.104431,320.56485}} wnTs[0]=0.998307 {{{2551,64}, {127,321}}}
SkOpSegment::addT insert t=0.453154928 segID=5 spanID=47
SkOpSegment::addT insert t=0.998306753 segID=14 spanID=48
debugShowLineIntersection wtTs[0]=0.575644854 {{{32,16}, {100,512}}} {{71.1438522,301.519836}} wtTs[1]=1 {{100,512}} wnTs[0]=3.15199e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=3.13901276e-07
SkOpSegment::addT insert t=0.575644854 segID=6 spanID=49
SkOpSegment::addT insert t=3.15199326e-07 segID=12 spanID=50
SkOpSegment::addT insert t=3.13901276e-07 segID=12 spanID=51
debugShowLineIntersection wtTs[0]=0.120346555 {{{32,16}, {100,512}}} {{40.183567,75.6918945}} wtTs[1]=1 {{100,512}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} wnTs[1]=0.999999886
SkOpSegment::addT insert t=0.120346555 segID=6 spanID=52
SkOpSegment::addT insert t=0.999999883 segID=13 spanID=53
SkOpSegment::addT insert t=0.999999886 segID=13 spanID=54
debugShowLineIntersection wtTs[0]=0 {{{100,512}, {213.229446,572.949036}}} {{100,512}} wtTs[1]=1 {{213.229446,572.949036}} wnTs[0]=3.13901e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=3.08641951e-07
debugShowLineIntersection wtTs[0]=0 {{{100,512}, {213.229446,572.949036}}} {{100,512}} wtTs[1]=1 {{213.229446,572.949036}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} wnTs[1]=0.999999891
debugShowLineIntersection wtTs[0]=0 {{{213.229446,572.949036}, {360,1024}}} {{213.229446,572.949036}} wtTs[1]=1 {{360,1024}} wnTs[0]=3.08642e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=3.01905369e-07
SkOpSegment::addT insert t=3.01905369e-07 segID=12 spanID=55
debugShowLineIntersection wtTs[0]=0 {{{213.229446,572.949036}, {360,1024}}} {{213.229446,572.949036}} wtTs[1]=1 {{360,1024}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} wnTs[1]=0.999999898
SkOpSegment::addT insert t=0.999999898 segID=13 spanID=56
debugShowLineIntersection wtTs[0]=3.01905369e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} {{360,1024}} wnTs[0]=0 {{{360,1024}, {360,4140}}}
debugShowLineIntersection wtTs[0]=0.999999897 {{{-2.14748365e+10,100000000}, {2551,64}}} {{360,4140}} wnTs[0]=1 {{{360,1024}, {360,4140}}}
SkOpSegment::addT insert t=0.999999897 segID=13 spanID=57
debugShowLineIntersection wtTs[0]=0.034708774 {{{127,321}, {6840,270}}} {{360,319.229858}} wnTs[0]=1.77918e-06 {{{360,4140}, {360,-2.14748365e+09}}}
SkOpSegment::addT insert t=1.77918132e-06 segID=10 spanID=58
SkOpSegment::addT insert t=0.034708774 segID=11 spanID=59
debugShowLineIntersection wtTs[0]=3.02581027e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} {{360,4140}} wnTs[0]=0 {{{360,4140}, {360,-2.14748365e+09}}}
SkOpSegment::addT insert t=3.02581027e-07 segID=12 spanID=60
debugShowLineIntersection wtTs[0]=0.999999897 {{{-2.14748365e+10,100000000}, {2551,64}}} {{360,4140}} wnTs[0]=0 {{{360,4140}, {360,-2.14748365e+09}}}
debugShowLineIntersection wtTs[0]=0.903877888 {{{2551,64}, {127,321}}} {{360,296.296631}} wnTs[0]=1.78986e-06 {{{360,4140}, {360,-2.14748365e+09}}}
SkOpSegment::addT insert t=1.78986041e-06 segID=10 spanID=61
SkOpSegment::addT insert t=0.903877888 segID=14 spanID=62
debugShowLineIntersection wtTs[0]=0 {{{127,321}, {6840,270}}} {{127,321}} wtTs[1]=1 {{6840,270}} wnTs[0]=3.12603e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} wnTs[1]=0
SkOpSegment::addT insert t=3.12602603e-07 segID=12 spanID=63
debugShowLineIntersection wtTs[0]=0 {{{127,321}, {6840,270}}} {{127,321}} wnTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}}
SkOpSegment::addT insert t=0.999999887 segID=13 spanID=64
debugShowLineIntersection wtTs[0]=0 {{{127,321}, {6840,270}}} {{127,321}} wnTs[0]=1 {{{2551,64}, {127,321}}}
debugShowLineIntersection wtTs[0]=1 {{{6840,270}, {-2.14748365e+10,100000000}}} {{-2.14748365e+10,100000000}} wnTs[0]=0 {{{-2.14748365e+10,100000000}, {2551,64}}}
debugShowLineIntersection wtTs[0]=3.03529974e-07 {{{6840,270}, {-2.14748365e+10,100000000}}} {{321.741364,300.352905}} wnTs[0]=0.919661 {{{2551,64}, {127,321}}}
SkOpSegment::addT insert t=3.03529974e-07 segID=12 spanID=65
SkOpSegment::addT insert t=0.919661149 segID=14 spanID=66
debugShowLineIntersection wtTs[0]=1 {{{-2.14748365e+10,100000000}, {2551,64}}} {{2551,64}} wnTs[0]=0 {{{2551,64}, {127,321}}}
--x---x----------xx-xxxx----------x--- addExpanded
00: seg/base=13/38 coinSeg/Span/PtT=13/54/54 MergeMatches
01: seg/base=12/37 coinSeg/Span/PtT=12/51/51 MergeMatches
02: seg/base=13/38 coinSeg/Span/PtT=13/54/54 MergeMatches
03: seg/base=12/37 coinSeg/Span/PtT=12/51/51 MergeMatches
04: seg/base=13/38 coinSeg/Span/PtT=13/54/54 MergeMatches
05: seg/base=12/37 coinSeg/Span/PtT=12/51/51 MergeMatches
06: seg/base=13/38 coinSeg/Span/PtT=13/54/54 MergeMatches
07: seg/base=12/37 coinSeg/Span/PtT=12/51/51 MergeMatches
08: seg/base=13/40 coinSeg/Span/PtT=13/46/46 MergeMatches
09: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
10: seg/base=13/40 coinSeg/Span/PtT=13/46/46 MergeMatches
11: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
12: seg/base=13/40 coinSeg/Span/PtT=13/54/54 MergeMatches
13: seg/base=12/39 coinSeg/Span/PtT=12/51/51 MergeMatches
14: segment=7 MergeMatches
15: seg/base=13/40 coinSeg/Span/PtT=13/54/54 MergeMatches
16: seg/base=12/39 coinSeg/Span/PtT=12/51/51 MergeMatches
17: segment=7 MergeMatches
18: seg/base=13/54 coinSeg/Span/PtT=13/64/64 MergeMatches
19: seg/base=12/51 coinSeg/Span/PtT=12/63/63 MergeMatches
20: seg/base=13/54 coinSeg/Span/PtT=13/64/64 MergeMatches
21: seg/base=12/51 coinSeg/Span/PtT=12/63/63 MergeMatches
22: seg/base=13/54 coinSeg/Span/PtT=13/53/53 MergeMatches
23: seg/base=6/52 coinSeg/Span/PtT=6/12/12 MergeMatches
24: seg/base=13/54 coinSeg/Span/PtT=13/53/53 MergeMatches
25: seg/base=6/52 coinSeg/Span/PtT=6/12/12 MergeMatches
26: seg/base=13/40 coinSeg/Span/PtT=13/46/46 MergeMatches
27: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
28: seg/base=13/40 coinSeg/Span/PtT=13/46/46 MergeMatches
29: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
30: seg/base=13/40 coinSeg/Span/PtT=13/46/46 MergeMatches
31: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
32: seg/base=13/40 coinSeg/Span/PtT=13/46/46 MergeMatches
33: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
34: seg/base=13/56 coinSeg/Span/PtT=13/54/54 MergeMatches
35: seg/base=12/55 coinSeg/Span/PtT=12/51/51 MergeMatches
36: seg/base=13/56 coinSeg/Span/PtT=13/54/54 MergeMatches
37: seg/base=12/55 coinSeg/Span/PtT=12/51/51 MergeMatches
38: seg/base=13/56 coinSeg/Span/PtT=13/54/54 MergeMatches
39: seg/base=12/55 coinSeg/Span/PtT=12/51/51 MergeMatches
40: seg/base=13/56 coinSeg/Span/PtT=13/54/54 MergeMatches
41: seg/base=12/55 coinSeg/Span/PtT=12/51/51 MergeMatches
42: seg/base=12/60 coinSeg/Span/PtT=12/55/55 MergeMatches
43: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
44: segment=9 MergeMatches
45: seg/base=13/57 coinSeg/Span/PtT=13/56/56 MergeMatches
46: seg/base=12/60 coinSeg/Span/PtT=12/55/55 MergeMatches
47: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
48: segment=9 MergeMatches
49: seg/base=13/57 coinSeg/Span/PtT=13/56/56 MergeMatches
50: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=9/18/18 oppEndSpan=17 MissingCoin
51: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=9/17/17 oppEndSpan=18 MissingCoin
52: seg/base=13/57 coinSeg/Span/PtT=13/54/54 MergeMatches
53: seg/base=12/60 coinSeg/Span/PtT=12/51/51 MergeMatches
54: seg/base=13/57 coinSeg/Span/PtT=13/54/54 MergeMatches
55: seg/base=12/60 coinSeg/Span/PtT=12/51/51 MergeMatches
56: seg/base=13/56 coinSeg/Span/PtT=13/54/54 MergeMatches
57: seg/base=12/55 coinSeg/Span/PtT=12/51/51 MergeMatches
58: seg/base=13/56 coinSeg/Span/PtT=13/54/54 MergeMatches
59: seg/base=12/55 coinSeg/Span/PtT=12/51/51 MergeMatches
60: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=10/19/19 oppEndSpan=31 MissingCoin
61: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=10/31/31 oppEndSpan=19 MissingCoin
62: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=9/18/18 oppEndSpan=17 MissingCoin
63: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=9/17/17 oppEndSpan=18 MissingCoin
64: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=10/19/19 oppEndSpan=31 MissingCoin
65: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=10/31/31 oppEndSpan=19 MissingCoin
66: seg/base=13/64 coinSeg/Span/PtT=13/54/54 MergeMatches
67: seg/base=12/63 coinSeg/Span/PtT=12/51/51 MergeMatches
68: seg/base=13/64 coinSeg/Span/PtT=13/54/54 MergeMatches
69: seg/base=12/63 coinSeg/Span/PtT=12/51/51 MergeMatches
70: seg/base=13/56 coinSeg/Span/PtT=13/57/57 MergeMatches
71: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
72: seg/base=12/55 coinSeg/Span/PtT=12/60/60 MergeMatches
73: segment=9 MergeMatches
74: seg/base=13/56 coinSeg/Span/PtT=13/57/57 MergeMatches
75: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
76: seg/base=12/55 coinSeg/Span/PtT=12/60/60 MergeMatches
77: segment=9 MergeMatches
78: coinSeg/Span/PtT=13/25/25 endSpan=54 oppSeg/Span/PtT=12/24/24 oppEndSpan=51 MissingCoin
79: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
80: segment=9 MergeMatches
81: seg/base=13/57 coinSeg/Span/PtT=13/56/56 MergeMatches
82: seg/base=12/60 coinSeg/Span/PtT=12/55/55 MergeMatches
83: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
84: segment=9 MergeMatches
85: seg/base=13/57 coinSeg/Span/PtT=13/56/56 MergeMatches
86: seg/base=12/60 coinSeg/Span/PtT=12/55/55 MergeMatches
87: coinSeg/Span/PtT=12/51/51 endSpan=24 oppSeg/Span/PtT=13/54/54 oppEndSpan=25 MissingCoin
88: coinSeg/Span/PtT=13/64/64 endSpan=26 oppSeg/Span/PtT=14/28/28 oppEndSpan=27 MissingCoin
89: coinSeg/Span/PtT=12/65/65 endSpan=63 oppSeg/Span/PtT=14/66/66 oppEndSpan=28 MissingCoin
90: coinSeg/Span/PtT=13/25/25 endSpan=54 oppSeg/Span/PtT=12/24/24 oppEndSpan=51 MissingCoin
91: coinSeg/Span/PtT=12/51/51 endSpan=24 oppSeg/Span/PtT=13/54/54 oppEndSpan=25 MissingCoin
92: coinSeg/Span/PtT=13/64/64 endSpan=26 oppSeg/Span/PtT=14/28/28 oppEndSpan=27 MissingCoin
93: coinSeg/Span/PtT=12/65/65 endSpan=63 oppSeg/Span/PtT=14/66/66 oppEndSpan=28 MissingCoin
94: segment=11 ReturnFalse
95: seg/base=11/21 Fail
96: seg/base=11/42 Fail
97: seg/base=11/21 Fail
98: seg/base=11/42 Fail
99: seg/base=8/15 Fail
100: segment=11 ReturnFalse
101: segment=11 startT=0.0126699 endT=0.0342199 segment=8 oppStartT=0 oppEndT=1 AddMissingCoin
102: segment=11 ReturnFalse
103: seg/base=7/13 Fail
104: seg/base=11/21 Fail
105: seg/base=11/42 Fail
106: seg/base=7/13 Fail
107: segment=11 ReturnFalse
108: segment=11 startT=0 endT=0.0126699 segment=7 oppStartT=0.246928 oppEndT=1 AddMissingCoin
109: segment=11 ReturnFalse
110: seg/base=5/9 Fail
111: seg/base=5/41 Fail
112: seg/base=5/47 Fail
113: seg/base=11/21 Fail
114: seg/base=11/42 Fail
115: segment=11 ReturnFalse
116: segment=11 startT=0 endT=0.0126699 segment=5 oppStartT=0.476143 oppEndT=0 AddMissingCoin
117: segment=11 ReturnFalse
118: seg/base=11/21 Fail
119: seg/base=11/42 Fail
120: seg/base=4/7 Fail
121: seg/base=4/29 Fail
122: seg/base=11/21 Fail
123: seg/base=11/42 Fail
124: seg/base=11/59 Fail
125: segment=11 ReturnFalse
126: segment=11 startT=0.0126699 endT=0.102205 segment=4 oppStartT=1 oppEndT=0 AddMissingCoin
127: segment=11 ReturnFalse
128: seg/base=11/21 Fail
129: seg/base=11/42 Fail
130: seg/base=11/59 Fail
131: seg/base=3/5 Fail
132: seg/base=3/35 Fail
133: seg/base=3/33 Fail
134: seg/base=11/21 Fail
135: seg/base=11/42 Fail
136: seg/base=11/59 Fail
137: seg/base=11/34 Fail
138: seg/base=3/5 Fail
139: segment=11 ReturnFalse
140: segment=11 startT=0.102205 endT=0.115176 segment=3 oppStartT=1 oppEndT=0.0649612 AddMissingCoin
141: segment=13 ReturnFalse
142: segment=13 startT=1 endT=1 segment=12 oppStartT=3.08642e-07 oppEndT=3.01905e-07 AddMissingCoin
143: segment=8 ReturnFalse
144: seg/base=8/15 Fail
145: seg/base=4/7 Fail
146: seg/base=4/29 Fail
147: segment=8 ReturnFalse
148: segment=8 startT=0 endT=1 segment=4 oppStartT=1 oppEndT=0.759312 AddMissingCoin
149: segment=8 ReturnFalse
150: seg/base=8/15 Fail
151: seg/base=4/7 Fail
152: seg/base=4/29 Fail
153: segment=8 ReturnFalse
154: segment=8 startT=0 endT=1 segment=4 oppStartT=1 oppEndT=0.759312 AddMissingCoin
155: segment=13 ReturnFalse
156: segment=13 startT=1 endT=1 segment=12 oppStartT=3.13901e-07 oppEndT=3.08642e-07 AddMissingCoin
157: segment=7 ReturnFalse
158: seg/base=5/9 Fail
159: seg/base=5/41 Fail
160: seg/base=5/47 Fail
161: seg/base=5/43 Fail
162: segment=7 ReturnFalse
163: segment=7 startT=0 endT=1 segment=5 oppStartT=0.632267 oppEndT=0 AddMissingCoin
164: segment=7 ReturnFalse
165: seg/base=7/13 Fail
166: seg/base=5/9 Fail
167: seg/base=5/41 Fail
168: seg/base=5/47 Fail
169: segment=7 ReturnFalse
170: segment=7 startT=0.228492 endT=1 segment=5 oppStartT=0.487799 oppEndT=0 AddMissingCoin
171: segment=13 ReturnFalse
172: seg/base=13/25 Fail
173: seg/base=13/53 Fail
174: seg/base=13/46 Fail
175: seg/base=12/23 Fail
176: seg/base=12/36 Fail
177: seg/base=12/37 Fail
178: seg/base=12/55 Fail
179: seg/base=12/60 Fail
180: seg/base=12/65 Fail
181: seg/base=12/39 Fail
182: seg/base=12/63 Fail
183: seg/base=12/44 Fail
184: seg/base=12/51 Fail
185: segment=13 ReturnFalse
186: segment=13 startT=1 endT=1 segment=12 oppStartT=3.15199e-07 oppEndT=3.13901e-07 AddMissingCoin
187: segment=6 ReturnFalse
188: seg/base=6/11 Fail
189: seg/base=6/52 Fail
190: seg/base=5/9 Fail
191: seg/base=5/41 Fail
192: seg/base=5/47 Fail
193: seg/base=5/43 Fail
194: seg/base=6/11 Fail
195: seg/base=6/52 Fail
196: seg/base=6/49 Fail
197: seg/base=5/9 Fail
198: seg/base=5/41 Fail
199: seg/base=5/47 Fail
200: seg/base=5/43 Fail
201: segment=6 ReturnFalse
202: segment=6 startT=0.291197 endT=1 segment=5 oppStartT=0.892917 oppEndT=0.632267 AddMissingCoin
203: segment=13 ReturnFalse
204: seg/base=13/25 Fail
205: seg/base=13/53 Fail
206: seg/base=13/46 Fail
207: seg/base=13/54 Fail
208: seg/base=12/23 Fail
209: seg/base=12/36 Fail
210: seg/base=12/37 Fail
211: seg/base=12/55 Fail
212: seg/base=12/60 Fail
213: seg/base=12/65 Fail
214: seg/base=12/39 Fail
215: seg/base=12/63 Fail
216: segment=13 ReturnFalse
217: segment=13 startT=1 endT=1 segment=12 oppStartT=3.127e-07 oppEndT=3.08642e-07 AddMissingCoin
218: segment=13 ReturnFalse
219: segment=13 startT=1 endT=1 segment=12 oppStartT=3.08642e-07 oppEndT=2.80653e-07 AddMissingCoin
220: segment=13 ReturnFalse
221: seg/base=13/25 Fail
222: seg/base=13/53 Fail
223: seg/base=13/46 Fail
224: seg/base=13/54 Fail
225: seg/base=13/64 Fail
226: seg/base=13/40 Fail
227: seg/base=13/57 Fail
228: seg/base=13/56 Fail
229: seg/base=13/38 Fail
230: seg/base=12/23 Fail
231: segment=13 ReturnFalse
232: segment=13 startT=1 endT=1 segment=12 oppStartT=2.80653e-07 oppEndT=2.76598e-07 AddMissingCoin
233: seg/base=11/42 startT=3.12405e-07 AddExpandedCoin
234: seg/base=12/65 startT=0.0300077 AddExpandedCoin
235: seg/base=12/60 startT=0.0665796 AddExpandedCoin
236: seg/base=12/55 startT=0.146093 AddExpandedCoin
237: seg/base=12/37 startT=0.208476 AddExpandedCoin
238: seg/base=12/36 startT=0.228359 AddExpandedCoin
239: seg/base=13/57 startT=0.899703 AddExpandedCoin
240: seg/base=12/65 startT=0.758838 AddExpandedCoin
241: seg/base=12/60 startT=3.73071 AddExpandedCoin
242: seg/base=13/64 startT=0.246928 AddExpandedCoin
243: seg/base=12/44 startT=0.228492 AddExpandedCoin
244: seg/base=12/63 startT=0.320059 AddExpandedCoin
245: seg/base=13/46 startT=0.291197 AddExpandedCoin
246: seg/base=13/54 startT=0.632267 AddExpandedCoin
247: seg/base=13/64 startT=0.367348 AddExpandedCoin
248: seg/base=5/41 startT=1 AddExpandedCoin
249: seg/base=5/41 startT=3.12405e-07 AddExpandedCoin
250: seg/base=5/47 startT=3.12605e-07 AddExpandedCoin
251: seg/base=13/57 startT=0.783452 AddExpandedCoin
252: seg/base=13/56 startT=0.733122 AddExpandedCoin
253: seg/base=4/29 startT=3.01825e-07 AddExpandedCoin
254: seg/base=12/60 startT=1.54926 AddExpandedCoin
255: seg/base=12/65 startT=1.67578 AddExpandedCoin
256: seg/base=3/33 startT=1 AddExpandedCoin
257: seg/base=3/35 startT=1 AddExpandedCoin
258: seg/base=3/33 startT=2.76716e-07 AddExpandedCoin
259: seg/base=11/21 seg/base=12/23 MarkCoinStart
260: seg/base=11/22 seg/base=12/63 MarkCoinEnd
261: coinSeg/Span/PtT=11/21/21 endSpan=22 Fail
262: seg/base=11/42 segment=12 MarkCoinMissing
263: seg/base=11/59 segment=12 MarkCoinMissing
264: seg/base=11/34 segment=12 MarkCoinMissing
265: seg/base=12/36 segment=11 MarkCoinMissing
266: seg/base=12/37 segment=11 MarkCoinMissing
267: seg/base=12/55 segment=11 MarkCoinMissing
268: seg/base=12/60 segment=11 MarkCoinMissing
269: seg/base=12/65 segment=11 MarkCoinMissing
270: seg/base=12/39 segment=11 MarkCoinMissing
271: seg/base=13/40 seg/base=8/15 MarkCoinStart
272: seg/base=13/56 seg/base=8/16 MarkCoinEnd
273: coinSeg/Span/PtT=13/40/40 endSpan=56 Fail
274: seg/base=13/57 segment=8 MarkCoinMissing
275: seg/base=8/15 seg/base=12/55 MarkCoinStart
276: seg/base=8/16 seg/base=12/39 MarkCoinEnd
277: seg/base=12/60 segment=8 MarkCoinMissing
278: seg/base=12/65 segment=8 MarkCoinMissing
279: seg/base=13/54 seg/base=7/13 MarkCoinStart
280: seg/base=13/40 seg/base=7/14 MarkCoinEnd
281: coinSeg/Span/PtT=13/54/54 endSpan=40 Fail
282: seg/base=13/64 segment=7 MarkCoinMissing
283: seg/base=7/13 seg/base=12/39 MarkCoinStart
284: seg/base=7/14 seg/base=12/51 MarkCoinEnd
285: seg/base=12/63 segment=7 MarkCoinMissing
286: seg/base=12/44 segment=7 MarkCoinMissing
287: seg/base=13/53 seg/base=6/52 MarkCoinStart
288: seg/base=13/54 seg/base=6/12 MarkCoinEnd
289: coinSeg/Span/PtT=13/53/53 endSpan=54 Fail
290: seg/base=13/46 segment=6 MarkCoinMissing
291: seg/base=6/49 segment=13 MarkCoinMissing
292: seg/base=6/49 seg/base=12/51 MarkCoinStart
293: seg/base=6/12 seg/base=12/50 MarkCoinEnd
294: seg/base=13/46 seg/base=5/9 MarkCoinStart
295: seg/base=13/40 seg/base=5/45 MarkCoinEnd
296: coinSeg/Span/PtT=13/46/46 endSpan=40 Fail
297: seg/base=13/54 segment=5 MarkCoinMissing
298: seg/base=13/64 segment=5 MarkCoinMissing
299: seg/base=5/41 segment=13 MarkCoinMissing
300: seg/base=5/47 segment=13 MarkCoinMissing
301: seg/base=5/43 segment=13 MarkCoinMissing
302: seg/base=5/9 seg/base=12/39 MarkCoinStart
303: seg/base=5/43 seg/base=12/44 MarkCoinEnd
304: coinSeg/Span/PtT=5/9/9 endSpan=43 Fail
305: seg/base=5/41 segment=12 MarkCoinMissing
306: seg/base=5/47 segment=12 MarkCoinMissing
307: seg/base=12/63 segment=5 MarkCoinMissing
308: seg/base=13/40 seg/base=4/7 MarkCoinStart
309: seg/base=13/38 seg/base=4/8 MarkCoinEnd
310: coinSeg/Span/PtT=13/40/40 endSpan=38 Fail
311: seg/base=13/57 segment=4 MarkCoinMissing
312: seg/base=13/56 segment=4 MarkCoinMissing
313: seg/base=4/29 segment=13 MarkCoinMissing
314: seg/base=4/7 seg/base=12/37 MarkCoinStart
315: seg/base=4/8 seg/base=12/39 MarkCoinEnd
316: coinSeg/Span/PtT=4/7/7 endSpan=8 Fail
317: seg/base=4/29 segment=12 MarkCoinMissing
318: seg/base=12/55 segment=4 MarkCoinMissing
319: seg/base=12/60 segment=4 MarkCoinMissing
320: seg/base=12/65 segment=4 MarkCoinMissing
321: seg/base=13/38 seg/base=3/5 MarkCoinStart
322: seg/base=13/32 seg/base=3/6 MarkCoinEnd
323: seg/base=3/35 segment=13 MarkCoinMissing
324: seg/base=3/33 segment=13 MarkCoinMissing
325: seg/base=3/35 seg/base=12/36 MarkCoinStart
326: seg/base=3/6 seg/base=12/37 MarkCoinEnd
327: coinSeg/Span/PtT=3/35/35 endSpan=6 Fail
328: seg/base=3/33 segment=12 MarkCoinMissing
329: seg/base=9/17 seg/base=10/19 MarkCoinStart
330: seg/base=9/18 seg/base=10/31 MarkCoinEnd
SkOpSegment::debugShowActiveSpans id=1 (360,-2.14748365e+09 593011648,-2.14748352e+09 1.07374221e+09,-1.6667529e+09 1.07374208e+09,-1.07374157e+09) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=2 (1.07374208e+09,-1.07374157e+09 1.07374208e+09,-480730560 593011840,-135.508026 905.953125,255.999786) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (905.953125,255.999786 900.097229,297.65976) t=0 tEnd=0.0649612467 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (900.097229,297.65976 897.639343,315.145294) t=0.0649612467 tEnd=0.0922268392 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (897.639343,315.145294 815.80835,897.304565) t=0.0922268392 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (815.80835,897.304565 360,651.952515) t=0 tEnd=0.756429319 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (360,651.952515 213.229446,572.949036) t=0.756429319 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (213.229446,572.949036 131.235565,320.967834) t=0 tEnd=0.452431368 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (131.235565,320.967834 131.104431,320.56485) t=0.452431368 tEnd=0.453154928 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (131.104431,320.56485 124.825912,301.269867) t=0.453154928 tEnd=0.487798966 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (124.825912,301.269867 51.4065475,75.6396332) t=0.487798966 tEnd=0.892917257 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (51.4065475,75.6396332 32,16) t=0.892917257 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (32,16 40.183567,75.6918945) t=0 tEnd=0.120346555 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (40.183567,75.6918945 71.1438522,301.519836) t=0.120346555 tEnd=0.575644854 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (71.1438522,301.519836 100,512) t=0.575644854 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=7 (100,512 213.229446,572.949036) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=8 (213.229446,572.949036 360,1024) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=9 (360,1024 360,4140) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,4140 360,1024) t=0 tEnd=1.45099777e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,1024 360,651.952515) t=1.45099777e-06 tEnd=1.62424554e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,651.952515 360,319.229858) t=1.62424554e-06 tEnd=1.77918132e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,319.229858 360,296.296631) t=1.77918132e-06 tEnd=1.78986041e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,296.296631 360,-2.14748365e+09) t=1.78986041e-06 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (127,321 131.235565,320.967834) t=0 tEnd=0.000630948916 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (131.235565,320.967834 360,319.229858) t=0.000630948916 tEnd=0.034708774 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (360,319.229858 897.639343,315.145294) t=0.034708774 tEnd=0.114798057 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (897.639343,315.145294 6840,270) t=0.114798057 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (6840,270 900.097229,297.65976) t=0 tEnd=2.7659819e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (900.097229,297.65976 813.017944,298.065247) t=2.7659819e-07 tEnd=2.80653133e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (813.017944,298.065247 360,1024) t=2.80653133e-07 tEnd=3.01905369e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (360,1024 360,4140) t=3.01905369e-07 tEnd=3.02581027e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (360,4140 321.741364,300.352905) t=3.02581027e-07 tEnd=3.03529974e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (321.741364,300.352905 211.962463,300.864105) t=3.03529974e-07 tEnd=3.08641951e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (211.962463,300.864105 127,321) t=3.08641951e-07 tEnd=3.12602603e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (127,321 124.825912,301.269867) t=3.12602603e-07 tEnd=3.12699562e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (124.825912,301.269867 100,512) t=3.12699562e-07 tEnd=3.13901276e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (100,512 71.1438522,301.519836) t=3.13901276e-07 tEnd=3.15199326e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (71.1438522,301.519836 -2.14748365e+10,100000000) t=3.15199326e-07 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (-2.14748365e+10,100000000 40.183567,75.6918945) t=0 tEnd=0.999999883 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (40.183567,75.6918945 51.4065437,75.6396332) t=0.999999883 tEnd=0.999999884 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (51.4065437,75.6396332 100,512) t=0.999999884 tEnd=0.999999886 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (100,512 127,321) t=0.999999886 tEnd=0.999999887 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (127,321 210.910217,74.8968811) t=0.999999887 tEnd=0.999999891 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (210.910217,74.8968811 360,4140) t=0.999999891 tEnd=0.999999897 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (360,4140 360,1024) t=0.999999897 tEnd=0.999999898 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (360,1024 811.965698,72.0980072) t=0.999999898 tEnd=0.999999919 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (811.965698,72.0980072 905.094727,71.6643372) t=0.999999919 tEnd=0.999999923 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (905.094727,71.6643372 2551,64) t=0.999999923 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (2551,64 360,296.296631) t=0 tEnd=0.903877888 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (360,296.296631 321.741364,300.352905) t=0.903877888 tEnd=0.919661149 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (321.741364,300.352905 131.104431,320.56485) t=0.919661149 tEnd=0.998306753 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (131.104431,320.56485 127,321) t=0.998306753 tEnd=1 windSum=? windValue=1
SkOpSegment::addT insert t=3.12405367e-07 segID=12 spanID=67
SkOpSegment::addT insert t=0.0126699258 segID=11 spanID=68
SkOpSegment::addT insert t=0.0290228849 segID=11 spanID=69
SkOpSegment::addT insert t=0.0320585186 segID=11 spanID=70
SkOpSegment::addT insert t=0.0342199142 segID=11 spanID=71
SkOpSegment::addT insert t=3.0175255e-07 segID=12 spanID=72
SkOpSegment::addT insert t=0.102204746 segID=11 spanID=73
SkOpSegment::addT insert t=2.76716432e-07 segID=12 spanID=74
SkOpSegment::addT insert t=0.115176306 segID=11 spanID=75
SkOpSegment::addT insert t=0.899702926 segID=8 spanID=76
SkOpSegment::addT insert t=0.758838213 segID=8 spanID=77
SkOpSegment::addT insert t=0.246927782 segID=7 spanID=78
SkOpSegment::addT insert t=0.228492228 segID=7 spanID=79
SkOpSegment::addT insert t=0.284429982 segID=7 spanID=80
SkOpSegment::addT insert t=0.291197031 segID=6 spanID=81
SkOpSegment::addT insert t=0.999999884 segID=13 spanID=82
SkOpSegment::addT insert t=0.788316424 segID=5 spanID=83
SkOpSegment::addT insert t=0.632267074 segID=5 spanID=84
SkOpSegment::addT insert t=0.999999887 segID=13 spanID=85
SkOpSegment::addT insert t=0.476142764 segID=5 spanID=86
SkOpSegment::addT insert t=0.999999887 segID=13 spanID=87
SkOpSegment::addT insert t=0.999999887 segID=13 spanID=88
SkOpSegment::addT insert t=3.12411385e-07 segID=12 spanID=89
SkOpSegment::addT insert t=0.783451987 segID=4 spanID=90
SkOpSegment::addT insert t=0.759311649 segID=4 spanID=91
SkOpSegment::addT insert t=0.999999898 segID=13 spanID=92
SkOpSegment::addT insert t=0.753851653 segID=4 spanID=93
SkOpSegment::addT insert t=3.01824696e-07 segID=12 spanID=94
SkOpSegment::addT insert t=0.817356482 segID=4 spanID=95
SkOpSegment::addT insert t=0.999999923 segID=13 spanID=96
SkOpSegment::addT insert t=0.999999923 segID=13 spanID=97
--x---x----------xxxxxxx----------x--- move_multiples
00: seg/base=13/38 coinSeg/Span/PtT=13/85/85 MergeMatches
01: seg/base=12/37 coinSeg/Span/PtT=12/44/44 MergeMatches
02: seg/base=13/38 coinSeg/Span/PtT=13/85/85 MergeMatches
03: seg/base=12/37 coinSeg/Span/PtT=12/44/44 MergeMatches
04: seg/base=13/38 coinSeg/Span/PtT=13/85/85 MergeMatches
05: seg/base=12/37 coinSeg/Span/PtT=12/44/44 MergeMatches
06: seg/base=13/38 coinSeg/Span/PtT=13/85/85 MergeMatches
07: seg/base=12/37 coinSeg/Span/PtT=12/44/44 MergeMatches
08: seg/base=13/40 coinSeg/Span/PtT=13/82/82 MergeMatches
09: seg/base=5/83 coinSeg/Span/PtT=5/9/9 MergeMatches
10: seg/base=12/39 coinSeg/Span/PtT=12/50/50 MergeMatches
11: seg/base=13/40 coinSeg/Span/PtT=13/82/82 MergeMatches
12: seg/base=5/83 coinSeg/Span/PtT=5/9/9 MergeMatches
13: seg/base=12/39 coinSeg/Span/PtT=12/50/50 MergeMatches
14: seg/base=13/40 coinSeg/Span/PtT=13/85/85 MergeMatches
15: seg/base=12/39 coinSeg/Span/PtT=12/44/44 MergeMatches
16: seg/base=7/79 coinSeg/Span/PtT=7/14/14 MergeMatches
17: seg/base=5/43 coinSeg/Span/PtT=5/9/9 MergeMatches
18: seg/base=13/40 coinSeg/Span/PtT=13/85/85 MergeMatches
19: seg/base=12/39 coinSeg/Span/PtT=12/44/44 MergeMatches
20: seg/base=7/79 coinSeg/Span/PtT=7/14/14 MergeMatches
21: seg/base=5/43 coinSeg/Span/PtT=5/9/9 MergeMatches
22: seg/base=13/54 coinSeg/Span/PtT=13/82/82 MergeMatches
23: seg/base=5/84 coinSeg/Span/PtT=5/83/83 MergeMatches
24: seg/base=12/51 coinSeg/Span/PtT=12/50/50 MergeMatches
25: seg/base=6/49 coinSeg/Span/PtT=6/12/12 MergeMatches
26: seg/base=13/54 coinSeg/Span/PtT=13/82/82 MergeMatches
27: seg/base=5/84 coinSeg/Span/PtT=5/83/83 MergeMatches
28: seg/base=12/51 coinSeg/Span/PtT=12/50/50 MergeMatches
29: seg/base=6/49 coinSeg/Span/PtT=6/12/12 MergeMatches
30: seg/base=13/54 coinSeg/Span/PtT=13/53/53 MergeMatches
31: seg/base=6/52 coinSeg/Span/PtT=6/12/12 MergeMatches
32: seg/base=13/54 coinSeg/Span/PtT=13/53/53 MergeMatches
33: seg/base=6/52 coinSeg/Span/PtT=6/12/12 MergeMatches
34: seg/base=13/40 coinSeg/Span/PtT=13/82/82 MergeMatches
35: seg/base=5/83 coinSeg/Span/PtT=5/9/9 MergeMatches
36: seg/base=12/39 coinSeg/Span/PtT=12/50/50 MergeMatches
37: seg/base=13/40 coinSeg/Span/PtT=13/82/82 MergeMatches
38: seg/base=5/83 coinSeg/Span/PtT=5/9/9 MergeMatches
39: seg/base=12/39 coinSeg/Span/PtT=12/50/50 MergeMatches
40: seg/base=13/40 coinSeg/Span/PtT=13/82/82 MergeMatches
41: seg/base=5/83 coinSeg/Span/PtT=5/9/9 MergeMatches
42: seg/base=12/39 coinSeg/Span/PtT=12/50/50 MergeMatches
43: seg/base=13/40 coinSeg/Span/PtT=13/82/82 MergeMatches
44: seg/base=5/83 coinSeg/Span/PtT=5/9/9 MergeMatches
45: seg/base=12/39 coinSeg/Span/PtT=12/50/50 MergeMatches
46: seg/base=13/56 coinSeg/Span/PtT=13/85/85 MergeMatches
47: seg/base=12/55 coinSeg/Span/PtT=12/44/44 MergeMatches
48: seg/base=13/56 coinSeg/Span/PtT=13/85/85 MergeMatches
49: seg/base=12/55 coinSeg/Span/PtT=12/44/44 MergeMatches
50: seg/base=13/56 coinSeg/Span/PtT=13/85/85 MergeMatches
51: seg/base=12/55 coinSeg/Span/PtT=12/44/44 MergeMatches
52: seg/base=13/56 coinSeg/Span/PtT=13/85/85 MergeMatches
53: seg/base=12/55 coinSeg/Span/PtT=12/44/44 MergeMatches
54: seg/base=10/30 coinSeg/Span/PtT=10/19/19 MergeMatches
55: seg/base=4/90 coinSeg/Span/PtT=4/29/29 MergeMatches
56: seg/base=12/60 coinSeg/Span/PtT=12/94/94 MergeMatches
57: seg/base=13/57 coinSeg/Span/PtT=13/92/92 MergeMatches
58: seg/base=10/30 coinSeg/Span/PtT=10/19/19 MergeMatches
59: seg/base=4/90 coinSeg/Span/PtT=4/29/29 MergeMatches
60: seg/base=12/60 coinSeg/Span/PtT=12/94/94 MergeMatches
61: seg/base=13/57 coinSeg/Span/PtT=13/92/92 MergeMatches
62: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=9/18/18 oppEndSpan=17 MissingCoin
63: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=9/17/17 oppEndSpan=18 MissingCoin
64: seg/base=12/60 coinSeg/Span/PtT=12/23/23 MergeMatches
65: seg/base=11/70 coinSeg/Span/PtT=11/22/22 MergeMatches
66: seg/base=12/60 coinSeg/Span/PtT=12/23/23 MergeMatches
67: seg/base=11/70 coinSeg/Span/PtT=11/22/22 MergeMatches
68: seg/base=13/56 coinSeg/Span/PtT=13/85/85 MergeMatches
69: seg/base=12/55 coinSeg/Span/PtT=12/44/44 MergeMatches
70: seg/base=13/56 coinSeg/Span/PtT=13/85/85 MergeMatches
71: seg/base=12/55 coinSeg/Span/PtT=12/44/44 MergeMatches
72: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=10/19/19 oppEndSpan=31 MissingCoin
73: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=10/31/31 oppEndSpan=19 MissingCoin
74: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=9/18/18 oppEndSpan=17 MissingCoin
75: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=9/17/17 oppEndSpan=18 MissingCoin
76: coinSeg/Span/PtT=13/57/57 endSpan=56 oppSeg/Span/PtT=10/19/19 oppEndSpan=31 MissingCoin
77: coinSeg/Span/PtT=12/55/55 endSpan=60 oppSeg/Span/PtT=10/31/31 oppEndSpan=19 MissingCoin
78: seg/base=13/64 coinSeg/Span/PtT=13/82/82 MergeMatches
79: seg/base=5/86 coinSeg/Span/PtT=5/83/83 MergeMatches
80: seg/base=12/63 coinSeg/Span/PtT=12/50/50 MergeMatches
81: seg/base=13/64 coinSeg/Span/PtT=13/82/82 MergeMatches
82: seg/base=5/86 coinSeg/Span/PtT=5/83/83 MergeMatches
83: seg/base=12/63 coinSeg/Span/PtT=12/50/50 MergeMatches
84: seg/base=13/56 coinSeg/Span/PtT=13/88/88 MergeMatches
85: seg/base=11/71 coinSeg/Span/PtT=11/42/42 MergeMatches
86: seg/base=12/55 coinSeg/Span/PtT=12/67/67 MergeMatches
87: seg/base=13/56 coinSeg/Span/PtT=13/88/88 MergeMatches
88: seg/base=11/71 coinSeg/Span/PtT=11/42/42 MergeMatches
89: seg/base=12/55 coinSeg/Span/PtT=12/67/67 MergeMatches
90: coinSeg/Span/PtT=13/25/25 endSpan=82 oppSeg/Span/PtT=12/24/24 oppEndSpan=50 MissingCoin
91: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
92: segment=9 MergeMatches
93: seg/base=8/76 coinSeg/Span/PtT=8/16/16 MergeMatches
94: seg/base=13/57 coinSeg/Span/PtT=13/56/56 MergeMatches
95: seg/base=4/90 coinSeg/Span/PtT=4/91/91 MergeMatches
96: seg/base=12/60 coinSeg/Span/PtT=12/55/55 MergeMatches
97: seg/base=11/70 coinSeg/Span/PtT=11/71/71 MergeMatches
98: seg/base=10/31 coinSeg/Span/PtT=10/19/19 MergeMatches
99: segment=9 MergeMatches
100: seg/base=8/76 coinSeg/Span/PtT=8/16/16 MergeMatches
101: seg/base=13/57 coinSeg/Span/PtT=13/56/56 MergeMatches
102: seg/base=4/90 coinSeg/Span/PtT=4/91/91 MergeMatches
103: seg/base=12/60 coinSeg/Span/PtT=12/55/55 MergeMatches
104: seg/base=11/70 coinSeg/Span/PtT=11/71/71 MergeMatches
105: coinSeg/Span/PtT=12/50/50 endSpan=24 oppSeg/Span/PtT=13/82/82 oppEndSpan=25 MissingCoin
106: coinSeg/Span/PtT=13/25/25 endSpan=82 oppSeg/Span/PtT=12/24/24 oppEndSpan=50 MissingCoin
107: coinSeg/Span/PtT=12/50/50 endSpan=24 oppSeg/Span/PtT=13/82/82 oppEndSpan=25 MissingCoin
108: segment=11 ReturnFalse
109: segment=11 startT=0.0126699 endT=0.0342199 segment=8 oppStartT=0 oppEndT=1 AddMissingCoin
110: segment=11 ReturnFalse
111: segment=11 startT=0 endT=0.0126699 segment=7 oppStartT=0.246928 oppEndT=1 AddMissingCoin
112: segment=11 ReturnFalse
113: segment=11 startT=0 endT=0.0126699 segment=5 oppStartT=0.476143 oppEndT=0 AddMissingCoin
114: segment=11 ReturnFalse
115: segment=11 startT=0.0126699 endT=0.102205 segment=4 oppStartT=1 oppEndT=0 AddMissingCoin
116: segment=11 ReturnFalse
117: segment=11 startT=0.102205 endT=0.115176 segment=3 oppStartT=1 oppEndT=0.0649612 AddMissingCoin
118: segment=13 ReturnFalse
119: segment=13 startT=1 endT=1 segment=12 oppStartT=3.08642e-07 oppEndT=3.01905e-07 AddMissingCoin
120: segment=8 ReturnFalse
121: segment=8 startT=0 endT=1 segment=4 oppStartT=1 oppEndT=0.759312 AddMissingCoin
122: segment=8 ReturnFalse
123: segment=8 startT=0 endT=1 segment=4 oppStartT=1 oppEndT=0.759312 AddMissingCoin
124: segment=13 ReturnFalse
125: segment=13 startT=1 endT=1 segment=12 oppStartT=3.13901e-07 oppEndT=3.08642e-07 AddMissingCoin
126: segment=7 ReturnFalse
127: segment=7 startT=0 endT=1 segment=5 oppStartT=0.632267 oppEndT=0 AddMissingCoin
128: segment=7 ReturnFalse
129: segment=7 startT=0.228492 endT=1 segment=5 oppStartT=0.487799 oppEndT=0 AddMissingCoin
130: segment=13 ReturnFalse
131: segment=13 startT=1 endT=1 segment=12 oppStartT=3.15199e-07 oppEndT=3.13901e-07 AddMissingCoin
132: segment=6 ReturnFalse
133: segment=6 startT=0.291197 endT=1 segment=5 oppStartT=0.892917 oppEndT=0.632267 AddMissingCoin
134: segment=13 ReturnFalse
135: segment=13 startT=1 endT=1 segment=12 oppStartT=3.127e-07 oppEndT=3.08642e-07 AddMissingCoin
136: segment=13 ReturnFalse
137: segment=13 startT=1 endT=1 segment=12 oppStartT=3.08642e-07 oppEndT=2.80653e-07 AddMissingCoin
138: segment=13 ReturnFalse
139: segment=13 startT=1 endT=1 segment=12 oppStartT=2.80653e-07 oppEndT=2.76598e-07 AddMissingCoin
140: seg/base=12/89 startT=0.000611695 AddExpandedCoin
141: seg/base=12/94 startT=0.0689388 AddExpandedCoin
142: seg/base=8/77 startT=1 AddExpandedCoin
143: seg/base=13/87 startT=0.283286 AddExpandedCoin
144: seg/base=12/89 startT=0.530213 AddExpandedCoin
145: seg/base=4/95 startT=1 AddExpandedCoin
146: seg/base=4/93 startT=1 AddExpandedCoin
147: seg/base=11/21 seg/base=12/23 MarkCoinStart
148: seg/base=11/22 seg/base=12/63 MarkCoinEnd
149: seg/base=12/39 MarkCoinInsert
150: seg/base=12/65 MarkCoinInsert
151: seg/base=12/60 MarkCoinInsert
152: seg/base=12/55 MarkCoinInsert
153: seg/base=12/94 MarkCoinInsert
154: seg/base=12/37 MarkCoinInsert
155: seg/base=12/74 MarkCoinInsert
156: seg/base=12/36 MarkCoinInsert
157: seg/base=12/23 MarkCoinInsert
158: seg/base=11/34 MarkCoinInsert
159: seg/base=11/73 MarkCoinInsert
160: seg/base=11/59 MarkCoinInsert
161: seg/base=11/71 MarkCoinInsert
162: seg/base=12/94 segment=11 MarkCoinMissing
163: seg/base=11/70 MarkCoinInsert
164: seg/base=11/69 MarkCoinInsert
165: seg/base=11/68 MarkCoinInsert
166: seg/base=11/42 MarkCoinInsert
167: seg/base=11/21 MarkCoinInsert
168: seg/base=12/89 segment=11 MarkCoinMissing
169: seg/base=13/40 seg/base=8/15 MarkCoinStart
170: seg/base=13/56 seg/base=8/16 MarkCoinEnd
171: seg/base=8/76 MarkCoinInsert
172: seg/base=8/77 segment=13 MarkCoinMissing
173: seg/base=13/57 MarkCoinInsert
174: seg/base=8/15 seg/base=12/55 MarkCoinStart
175: seg/base=8/16 seg/base=12/39 MarkCoinEnd
176: seg/base=12/60 MarkCoinInsert
177: seg/base=12/55 MarkCoinInsert
178: seg/base=8/77 MarkCoinInsert
179: seg/base=8/15 MarkCoinInsert
180: seg/base=13/54 seg/base=7/13 MarkCoinStart
181: seg/base=13/40 seg/base=7/14 MarkCoinEnd
182: coinSeg/Span/PtT=13/54/54 endSpan=40 Fail
183: seg/base=7/79 MarkCoinInsert
184: seg/base=7/78 MarkCoinInsert
185: seg/base=13/87 segment=7 MarkCoinMissing
186: seg/base=7/80 MarkCoinInsert
187: seg/base=13/85 MarkCoinInsert
188: seg/base=13/64 MarkCoinInsert
189: seg/base=13/88 MarkCoinInsert
190: seg/base=7/13 seg/base=12/39 MarkCoinStart
191: seg/base=7/14 seg/base=12/51 MarkCoinEnd
192: seg/base=12/63 MarkCoinInsert
193: seg/base=12/89 MarkCoinInsert
194: seg/base=12/39 MarkCoinInsert
195: seg/base=7/78 MarkCoinInsert
196: seg/base=12/89 segment=7 MarkCoinMissing
197: seg/base=7/79 MarkCoinInsert
198: seg/base=7/13 MarkCoinInsert
199: seg/base=13/53 seg/base=6/52 MarkCoinStart
200: seg/base=13/54 seg/base=6/12 MarkCoinEnd
201: seg/base=6/81 MarkCoinInsert
202: seg/base=6/49 MarkCoinInsert
203: seg/base=13/46 MarkCoinInsert
204: seg/base=13/82 MarkCoinInsert
205: seg/base=6/49 seg/base=12/51 MarkCoinStart
206: seg/base=6/12 seg/base=12/50 MarkCoinEnd
207: seg/base=13/46 seg/base=5/9 MarkCoinStart
208: seg/base=13/40 seg/base=5/45 MarkCoinEnd
209: seg/base=5/84 MarkCoinInsert
210: seg/base=5/43 MarkCoinInsert
211: seg/base=5/86 MarkCoinInsert
212: seg/base=5/47 MarkCoinInsert
213: seg/base=5/41 MarkCoinInsert
214: seg/base=5/9 MarkCoinInsert
215: seg/base=13/87 MarkCoinInsert
216: seg/base=13/64 MarkCoinInsert
217: seg/base=13/85 MarkCoinInsert
218: seg/base=13/54 MarkCoinInsert
219: seg/base=13/82 MarkCoinInsert
220: seg/base=13/46 MarkCoinInsert
221: seg/base=5/9 seg/base=12/39 MarkCoinStart
222: seg/base=5/43 seg/base=12/44 MarkCoinEnd
223: seg/base=12/67 MarkCoinInsert
224: seg/base=12/89 MarkCoinInsert
225: seg/base=12/63 MarkCoinInsert
226: seg/base=5/41 MarkCoinInsert
227: seg/base=5/47 MarkCoinInsert
228: seg/base=5/86 MarkCoinInsert
229: seg/base=13/40 seg/base=4/7 MarkCoinStart
230: seg/base=13/38 seg/base=4/8 MarkCoinEnd
231: seg/base=4/91 MarkCoinInsert
232: seg/base=4/29 MarkCoinInsert
233: seg/base=4/93 MarkCoinInsert
234: seg/base=4/93 segment=13 MarkCoinMissing
235: seg/base=13/56 MarkCoinInsert
236: seg/base=13/57 MarkCoinInsert
237: seg/base=13/40 MarkCoinInsert
238: seg/base=4/95 segment=13 MarkCoinMissing
239: seg/base=4/7 seg/base=12/37 MarkCoinStart
240: seg/base=4/8 seg/base=12/39 MarkCoinEnd
241: seg/base=12/72 MarkCoinInsert
242: seg/base=12/94 MarkCoinInsert
243: seg/base=12/55 MarkCoinInsert
244: seg/base=12/60 MarkCoinInsert
245: seg/base=12/65 MarkCoinInsert
246: seg/base=4/93 MarkCoinInsert
247: seg/base=4/29 MarkCoinInsert
248: seg/base=4/91 MarkCoinInsert
249: seg/base=4/90 MarkCoinInsert
250: seg/base=4/95 MarkCoinInsert
251: seg/base=13/38 seg/base=3/5 MarkCoinStart
252: seg/base=13/32 seg/base=3/6 MarkCoinEnd
253: seg/base=3/35 MarkCoinInsert
254: seg/base=3/5 MarkCoinInsert
255: seg/base=13/96 MarkCoinInsert
256: seg/base=13/38 MarkCoinInsert
257: seg/base=3/35 seg/base=12/36 MarkCoinStart
258: seg/base=3/6 seg/base=12/37 MarkCoinEnd
259: seg/base=12/74 MarkCoinInsert
260: seg/base=3/33 MarkCoinInsert
261: seg/base=9/17 seg/base=10/19 MarkCoinStart
262: seg/base=9/18 seg/base=10/31 MarkCoinEnd
SkOpSegment::debugShowActiveSpans id=1 (360,-2.14748365e+09 593011648,-2.14748352e+09 1.07374221e+09,-1.6667529e+09 1.07374208e+09,-1.07374157e+09) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=2 (1.07374208e+09,-1.07374157e+09 1.07374208e+09,-480730560 593011840,-135.508026 905.953125,255.999786) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (905.953125,255.999786 900.097229,297.65976) t=0 tEnd=0.0649612467 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (900.097229,297.65976 897.639343,315.145294) t=0.0649612467 tEnd=0.0922268392 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (897.639343,315.145294 815.80835,897.304565) t=0.0922268392 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (815.80835,897.304565 361.553253,652.788635) t=0 tEnd=0.753851653 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (361.553253,652.788635 360,651.952515) t=0.753851653 tEnd=0.756429319 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (360,651.952515 358.263184,651.017639) t=0.756429319 tEnd=0.759311649 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (358.263184,651.017639 343.716705,643.187561) t=0.759311649 tEnd=0.783451987 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (343.716705,643.187561 323.286591,632.190491) t=0.783451987 tEnd=0.817356482 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=4 (323.286591,632.190491 213.229446,572.949036) t=0.817356482 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (213.229446,572.949036 131.235565,320.967834) t=0 tEnd=0.452431368 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (131.235565,320.967834 131.104431,320.56485) t=0.452431368 tEnd=0.453154928 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (131.104431,320.56485 126.938354,307.76178) t=0.453154928 tEnd=0.476142764 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (126.938354,307.76178 124.825912,301.269867) t=0.476142764 tEnd=0.487798966 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (124.825912,301.269867 98.6440353,220.808502) t=0.487798966 tEnd=0.632267074 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (98.6440353,220.808502 70.3632965,133.896957) t=0.632267074 tEnd=0.788316424 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (70.3632965,133.896957 51.4065475,75.6396332) t=0.788316424 tEnd=0.892917257 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (51.4065475,75.6396332 32,16) t=0.892917257 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (32,16 40.183567,75.6918945) t=0 tEnd=0.120346555 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (40.183567,75.6918945 51.8013992,160.433731) t=0.120346555 tEnd=0.291197031 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (51.8013992,160.433731 71.1438522,301.519836) t=0.291197031 tEnd=0.575644854 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (71.1438522,301.519836 100,512) t=0.575644854 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=7 (100,512 125.872047,525.926392) t=0 tEnd=0.228492228 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=7 (125.872047,525.926392 127.959496,527.049988) t=0.228492228 tEnd=0.246927782 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=7 (127.959496,527.049988 132.205856,529.335754) t=0.246927782 tEnd=0.284429982 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=7 (132.205856,529.335754 213.229446,572.949036) t=0.284429982 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=8 (213.229446,572.949036 324.604553,915.223755) t=0 tEnd=0.758838213 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=8 (324.604553,915.223755 345.279358,978.760925) t=0.758838213 tEnd=0.899702926 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=8 (345.279358,978.760925 360,1024) t=0.899702926 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=9 (360,1024 360,4140) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,4140 360,1024) t=0 tEnd=1.45099777e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,1024 360,651.952515) t=1.45099777e-06 tEnd=1.62424554e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,651.952515 360,319.229858) t=1.62424554e-06 tEnd=1.77918132e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,319.229858 360,296.296631) t=1.77918132e-06 tEnd=1.78986041e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,296.296631 360,-2.14748365e+09) t=1.78986041e-06 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (127,321 131.235565,320.967834) t=0 tEnd=0.000630948916 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (131.235565,320.967834 212.053207,320.353821) t=0.000630948916 tEnd=0.0126699258 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (212.053207,320.353821 321.830627,319.519836) t=0.0126699258 tEnd=0.0290228849 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (321.830627,319.519836 342.208832,319.365021) t=0.0290228849 tEnd=0.0320585186 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (342.208832,319.365021 356.718292,319.254791) t=0.0320585186 tEnd=0.0342199142 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (356.718292,319.254791 360,319.229858) t=0.0342199142 tEnd=0.034708774 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (360,319.229858 813.100464,315.787567) t=0.034708774 tEnd=0.102204746 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (813.100464,315.787567 897.639343,315.145294) t=0.102204746 tEnd=0.114798057 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (897.639343,315.145294 900.178528,315.126007) t=0.114798057 tEnd=0.115176306 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (900.178528,315.126007 6840,270) t=0.115176306 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (6840,270 900.097229,297.65976) t=0 tEnd=2.7659819e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (900.097229,297.65976 897.557983,297.67157) t=2.7659819e-07 tEnd=2.76716432e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (897.557983,297.67157 813.017944,298.065247) t=2.76716432e-07 tEnd=2.80653133e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (813.017944,298.065247 359.911255,300.175171) t=2.80653133e-07 tEnd=3.0175255e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (359.911255,300.175171 358.361938,300.182373) t=3.0175255e-07 tEnd=3.01824696e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (358.361938,300.182373 360,1024) t=3.01824696e-07 tEnd=3.01905369e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (360,1024 360,4140) t=3.01905369e-07 tEnd=3.02581027e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (360,4140 321.741364,300.352905) t=3.02581027e-07 tEnd=3.03529974e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (321.741364,300.352905 211.962463,300.864105) t=3.03529974e-07 tEnd=3.08641951e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (211.962463,300.864105 131.143692,301.240448) t=3.08641951e-07 tEnd=3.12405367e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (131.143692,301.240448 131.01445,301.241058) t=3.12405367e-07 tEnd=3.12411385e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (131.01445,301.241058 127,321) t=3.12411385e-07 tEnd=3.12602603e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (127,321 124.825912,301.269867) t=3.12602603e-07 tEnd=3.12699562e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (124.825912,301.269867 100,512) t=3.12699562e-07 tEnd=3.13901276e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (100,512 71.1438522,301.519836) t=3.13901276e-07 tEnd=3.15199326e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (71.1438522,301.519836 -2.14748365e+10,100000000) t=3.15199326e-07 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (-2.14748365e+10,100000000 40.183567,75.6918945) t=0 tEnd=0.999999883 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (40.183567,75.6918945 51.4065437,75.6396332) t=0.999999883 tEnd=0.999999884 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (51.4065437,75.6396332 70.0916061,75.5526199) t=0.999999884 tEnd=0.999999884 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (70.0916061,75.5526199 100,512) t=0.999999884 tEnd=0.999999886 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (100,512 123.773666,75.3026428) t=0.999999886 tEnd=0.999999887 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (123.773666,75.3026428 127,321) t=0.999999887 tEnd=0.999999887 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (127,321 129.962204,75.2738266) t=0.999999887 tEnd=0.999999887 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (129.962204,75.2738266 130.091461,75.2732239) t=0.999999887 tEnd=0.999999887 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (130.091461,75.2732239 210.910217,74.8968811) t=0.999999887 tEnd=0.999999891 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (210.910217,74.8968811 360,4140) t=0.999999891 tEnd=0.999999897 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (360,4140 360,1024) t=0.999999897 tEnd=0.999999898 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (360,1024 357.309692,74.2151566) t=0.999999898 tEnd=0.999999898 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (357.309692,74.2151566 811.965698,72.0980072) t=0.999999898 tEnd=0.999999919 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (811.965698,72.0980072 896.505737,71.7043304) t=0.999999919 tEnd=0.999999923 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (896.505737,71.7043304 899.044983,71.6925125) t=0.999999923 tEnd=0.999999923 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (899.044983,71.6925125 905.094727,71.6643372) t=0.999999923 tEnd=0.999999923 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (905.094727,71.6643372 2551,64) t=0.999999923 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (2551,64 360,296.296631) t=0 tEnd=0.903877888 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (360,296.296631 321.741364,300.352905) t=0.903877888 tEnd=0.919661149 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (321.741364,300.352905 131.104431,320.56485) t=0.919661149 tEnd=0.998306753 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (131.104431,320.56485 127,321) t=0.998306753 tEnd=1 windSum=? windValue=1
SkOpSegment::markDone id=4 (815.80835,897.304565 213.229446,572.949036) t=0 [7] (815.80835,897.304565) tEnd=0.753851653 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=4 (815.80835,897.304565 213.229446,572.949036) t=0.753851653 [93] (361.553253,652.788635) tEnd=0.756429319 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=4 (815.80835,897.304565 213.229446,572.949036) t=0.756429319 [29] (360,651.952515) tEnd=0.759311649 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=4 (815.80835,897.304565 213.229446,572.949036) t=0.759311649 [91] (358.263184,651.017639) tEnd=0.783451987 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=4 (815.80835,897.304565 213.229446,572.949036) t=0.783451987 [90] (343.716705,643.187561) tEnd=0.817356482 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=4 (815.80835,897.304565 213.229446,572.949036) t=0.817356482 [95] (323.286591,632.190491) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=7 (100,512 213.229446,572.949036) t=0 [13] (100,512) tEnd=0.246927782 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=7 (100,512 213.229446,572.949036) t=0.246927782 [78] (127.959496,527.049988) tEnd=0.284429982 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=7 (100,512 213.229446,572.949036) t=0.284429982 [80] (132.205856,529.335754) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=8 (213.229446,572.949036 360,1024) t=0 [15] (213.229446,572.949036) tEnd=0.758838213 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=8 (213.229446,572.949036 360,1024) t=0.758838213 [77] (324.604553,915.223755) tEnd=0.899702926 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=8 (213.229446,572.949036 360,1024) t=0.899702926 [76] (345.279358,978.760925) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
SkOpSegment::markDone id=9 (360,1024 360,4140) t=0 [17] (360,1024) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
------------------xx-xxx----x--x------ move_nearby
00: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
01: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
02: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
03: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
04: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
05: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
06: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
07: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
08: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
09: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
10: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
11: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
12: seg/base=12/89 coinSeg/Span/PtT=12/23/23 MergeMatches
13: seg/base=13/96 coinSeg/Span/PtT=13/87/87 MergeMatches
14: segment=11 MergeMatches
15: seg/base=5/47 coinSeg/Span/PtT=5/9/9 MergeMatches
16: seg/base=12/89 coinSeg/Span/PtT=12/23/23 MergeMatches
17: seg/base=13/96 coinSeg/Span/PtT=13/87/87 MergeMatches
18: segment=11 MergeMatches
19: seg/base=5/47 coinSeg/Span/PtT=5/9/9 MergeMatches
20: seg/base=4/90 coinSeg/Span/PtT=4/7/7 MoveNearbyRelease
21: seg/base=4/29 coinSeg/Span/PtT=4/7/7 MoveNearbyRelease
22: seg/base=4/91 coinSeg/Span/PtT=4/7/7 MoveNearbyRelease
23: seg/base=4/91 coinSeg/Span/PtT=4/29/29 MoveNearbyRelease
24: seg/base=4/90 coinSeg/Span/PtT=4/29/29 MoveNearbyRelease
25: seg/base=4/90 coinSeg/Span/PtT=4/91/91 MoveNearbyRelease
26: seg/base=4/29 coinSeg/Span/PtT=4/91/91 MoveNearbyRelease
27: seg/base=4/29 coinSeg/Span/PtT=4/90/90 MoveNearbyRelease
28: seg/base=4/91 coinSeg/Span/PtT=4/90/90 MoveNearbyRelease
29: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
30: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
31: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
32: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
33: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
34: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
35: seg/base=13/96 coinSeg/Span/PtT=13/87/87 MergeMatches
36: segment=11 MergeMatches
37: seg/base=5/47 coinSeg/Span/PtT=5/9/9 MergeMatches
38: seg/base=12/89 coinSeg/Span/PtT=12/23/23 MergeMatches
39: seg/base=13/96 coinSeg/Span/PtT=13/87/87 MergeMatches
40: segment=11 MergeMatches
41: seg/base=5/47 coinSeg/Span/PtT=5/9/9 MergeMatches
42: seg/base=12/89 coinSeg/Span/PtT=12/23/23 MergeMatches
43: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
44: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
45: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
46: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
47: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
48: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
49: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
50: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
51: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
52: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
53: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
54: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
55: seg/base=7/80 coinSeg/Span/PtT=7/13/13 MoveNearbyRelease
56: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
57: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
58: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
59: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
60: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
61: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
62: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
63: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
64: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
65: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
66: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
67: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
68: seg/base=8/76 coinSeg/Span/PtT=8/15/15 MoveNearbyRelease
69: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
70: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
71: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
72: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
73: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
74: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
75: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
76: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
77: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
78: seg/base=13/96 coinSeg/Span/PtT=13/46/46 MergeMatches
79: seg/base=6/81 coinSeg/Span/PtT=6/12/12 MergeMatches
80: seg/base=5/45 coinSeg/Span/PtT=5/9/9 MergeMatches
81: segment=9 MoveNearbyClearAll2
82: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
83: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
84: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
85: seg/base=12/72 coinSeg/Span/PtT=12/23/23 MergeMatches
86: seg/base=10/58 coinSeg/Span/PtT=10/19/19 MergeMatches
87: seg/base=11/59 coinSeg/Span/PtT=11/22/22 MergeMatches
88: seg/base=12/89 coinSeg/Span/PtT=12/23/23 MergeMatches
89: seg/base=5/47 coinSeg/Span/PtT=5/9/9 MergeMatches
90: segment=11 MergeMatches
91: seg/base=13/87 coinSeg/Span/PtT=13/96/96 MergeMatches
92: seg/base=12/89 coinSeg/Span/PtT=12/23/23 MergeMatches
93: seg/base=5/47 coinSeg/Span/PtT=5/9/9 MergeMatches
94: segment=11 MergeMatches
95: seg/base=13/87 coinSeg/Span/PtT=13/96/96 MergeMatches
96: coinSeg/Span/PtT=13/25/25 endSpan=87 oppSeg/Span/PtT=12/24/24 oppEndSpan=89 MissingCoin
97: coinSeg/Span/PtT=12/89/89 endSpan=24 oppSeg/Span/PtT=13/87/87 oppEndSpan=25 MissingCoin
98: coinSeg/Span/PtT=13/25/25 endSpan=87 oppSeg/Span/PtT=12/24/24 oppEndSpan=89 MissingCoin
99: coinSeg/Span/PtT=12/89/89 endSpan=24 oppSeg/Span/PtT=13/87/87 oppEndSpan=25 MissingCoin
100: seg/base=11/21 seg/base=12/23 MarkCoinStart
101: seg/base=11/22 seg/base=12/89 MarkCoinEnd
102: seg/base=12/72 MarkCoinInsert
103: seg/base=12/23 MarkCoinInsert
104: seg/base=11/69 MarkCoinInsert
105: seg/base=11/21 MarkCoinInsert
106: seg/base=13/46 seg/base=5/9 MarkCoinStart
107: seg/base=13/96 seg/base=5/45 MarkCoinEnd
108: seg/base=5/9 MarkCoinInsert
109: seg/base=13/46 MarkCoinInsert
110: seg/base=13/96 seg/base=3/5 MarkCoinStart
111: seg/base=13/32 seg/base=3/6 MarkCoinEnd
SkOpSegment::debugShowActiveSpans id=1 (360,-2.14748365e+09 593011648,-2.14748352e+09 1.07374221e+09,-1.6667529e+09 1.07374208e+09,-1.07374157e+09) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=2 (1.07374208e+09,-1.07374157e+09 1.07374208e+09,-480730560 593011840,-135.508026 905.953125,255.999786) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=3 (905.953125,255.999786 815.80835,897.304565) t=0 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (213.229446,572.949036 131.104431,320.56485) t=0 tEnd=0.453154928 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (131.104431,320.56485 51.4065475,75.6396332) t=0.453154928 tEnd=0.892917257 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=5 (51.4065475,75.6396332 32,16) t=0.892917257 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (32,16 51.8013992,160.433731) t=0 tEnd=0.291197031 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=6 (51.8013992,160.433731 100,512) t=0.291197031 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,4140 360,319.229858) t=0 tEnd=1.77918132e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,319.229858 360,296.296631) t=1.77918132e-06 tEnd=1.78986041e-06 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=10 (360,296.296631 360,-2.14748365e+09) t=1.78986041e-06 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (127,321 321.830627,319.519836) t=0 tEnd=0.0290228849 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (321.830627,319.519836 360,319.229858) t=0.0290228849 tEnd=0.034708774 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=11 (360,319.229858 6840,270) t=0.034708774 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (6840,270 359.911255,300.175171) t=0 tEnd=3.0175255e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (359.911255,300.175171 321.741364,300.352905) t=3.0175255e-07 tEnd=3.03529974e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (321.741364,300.352905 131.01445,301.241058) t=3.03529974e-07 tEnd=3.12411385e-07 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=12 (131.01445,301.241058 -2.14748365e+10,100000000) t=3.12411385e-07 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (-2.14748365e+10,100000000 51.4065437,75.6396332) t=0 tEnd=0.999999884 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (51.4065437,75.6396332 129.962204,75.2738266) t=0.999999884 tEnd=0.999999887 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (129.962204,75.2738266 896.505737,71.7043304) t=0.999999887 tEnd=0.999999923 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (896.505737,71.7043304 905.094727,71.6643372) t=0.999999923 tEnd=0.999999923 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=13 (905.094727,71.6643372 2551,64) t=0.999999923 tEnd=1 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (2551,64 360,296.296631) t=0 tEnd=0.903877888 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (360,296.296631 321.741364,300.352905) t=0.903877888 tEnd=0.919661149 windSum=? windValue=1
SkOpSegment::debugShowActiveSpans id=14 (321.741364,300.352905 127,321) t=0.919661149 tEnd=1 windSum=? windValue=1
c:\skia\src\pathops\skopsegment.cpp(1358): fatal error: "assert((this->globalState() && (this->globalState()->debugCheckHealth() || this->globalState()->debugSkipAssert())) || (!SkDPoint::ApproximatelyEqual(dBugRef->fPt, dBugCheck->fPt)))"
pathops_unittest.exe has triggered a breakpoint.
</div>
</div>
<script type="text/javascript">
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var testDivs = [
crbug_526025,
];
var decimal_places = 3; // make this 3 to show more precision
var tests = [];
var testLines = [];
var testTitles = [];
var testIndex = 0;
var ctx;
var xmin, xmax, focusXmin, focusXmax;
var ymin, ymax, focusYmin, focusYmax;
var scale;
var mouseX, mouseY;
var srcLeft, srcTop;
var screenWidth, screenHeight;
var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
var curveT = 0;
var pt_labels = 2;
var collect_bounds = false;
var control_lines = 0;
var curve_t = false;
var debug_xy = 1;
var focus_enabled = false;
var focus_on_selection = false;
var step_limit = 0;
var draw_active = false;
var draw_add = false;
var draw_angle = 0;
var draw_coincidence = false;
var draw_deriviatives = 0;
var draw_direction = false;
var draw_hints = false;
var draw_id = false;
var draw_intersection = 0;
var draw_intersectT = false;
var draw_legend = true;
var draw_log = false;
var draw_mark = false;
var draw_midpoint = false;
var draw_op = 0;
var draw_sequence = false;
var draw_sort = 0;
var draw_top = false;
var draw_path = 3;
var draw_computed = 0;
var retina_scale = !!window.devicePixelRatio;
var activeCount = 0;
var addCount = 0;
var angleCount = 0;
var coinCount = 0;
var opCount = 0;
var sectCount = 0;
var sortCount = 0;
var topCount = 0;
var markCount = 0;
var activeMax = 0;
var addMax = 0;
var angleMax = 0;
var coinMax = 0;
var sectMax = 0;
var sectMax2 = 0;
var sortMax = 0;
var topMax = 0;
var markMax = 0;
var opMax = 0;
var stepMax = 0;
var lastIndex = 0;
var hasPath = false;
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
var hasAlignedPath = false;
var hasComputedPath = false;
var angleBetween = false;
var afterIndex = 0;
var firstActiveSpan = -1;
var logStart = -1;
var logRange = 0;
var SPAN_ID = 0;
var SPAN_X1 = SPAN_ID + 1;
var SPAN_Y1 = SPAN_X1 + 1;
var SPAN_X2 = SPAN_Y1 + 1;
var SPAN_Y2 = SPAN_X2 + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_L_TX = SPAN_Y2 + 1;
var SPAN_L_TY = SPAN_L_TX + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_L_OTHER = SPAN_L_TY + 1;
var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
var SPAN_L_SUM = SPAN_L_OTHERI + 1;
var SPAN_L_VAL = SPAN_L_SUM + 1;
var SPAN_L_OPP = SPAN_L_VAL + 1;
var SPAN_X3 = SPAN_Y2 + 1;
var SPAN_Y3 = SPAN_X3 + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_Q_TX = SPAN_Y3 + 1;
var SPAN_Q_TY = SPAN_Q_TX + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_Q_OTHER = SPAN_Q_TY + 1;
var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
var SPAN_Q_VAL = SPAN_Q_SUM + 1;
var SPAN_Q_OPP = SPAN_Q_VAL + 1;
var SPAN_K_W = SPAN_Y3 + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_K_TX = SPAN_K_W + 1;
var SPAN_K_TY = SPAN_K_TX + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_K_OTHER = SPAN_K_TY + 1;
var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
var SPAN_K_SUM = SPAN_K_OTHERI + 1;
var SPAN_K_VAL = SPAN_K_SUM + 1;
var SPAN_K_OPP = SPAN_K_VAL + 1;
var SPAN_X4 = SPAN_Y3 + 1;
var SPAN_Y4 = SPAN_X4 + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_C_TX = SPAN_Y4 + 1;
var SPAN_C_TY = SPAN_C_TX + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var SPAN_C_OTHER = SPAN_C_TY + 1;
var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
var SPAN_C_SUM = SPAN_C_OTHERI + 1;
var SPAN_C_VAL = SPAN_C_SUM + 1;
var SPAN_C_OPP = SPAN_C_VAL + 1;
var ACTIVE_LINE_SPAN = 1;
var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
var ADD_LINETO = ADD_MOVETO + 1;
var ADD_QUADTO = ADD_LINETO + 1;
var ADD_CONICTO = ADD_QUADTO + 1;
var ADD_CUBICTO = ADD_CONICTO + 1;
var ADD_CLOSE = ADD_CUBICTO + 1;
var ADD_FILL = ADD_CLOSE + 1;
var PATH_LINE = ADD_FILL + 1;
var PATH_QUAD = PATH_LINE + 1;
var PATH_CONIC = PATH_QUAD + 1;
var PATH_CUBIC = PATH_CONIC + 1;
var INTERSECT_LINE = PATH_CUBIC + 1;
var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var INTERSECT_CONIC_QUAD = INTERSECT_CONIC_LINE_NO + 1;
var INTERSECT_CONIC_QUAD_2 = INTERSECT_CONIC_QUAD + 1;
var INTERSECT_CONIC_QUAD_3 = INTERSECT_CONIC_QUAD_2 + 1;
var INTERSECT_CONIC_QUAD_4 = INTERSECT_CONIC_QUAD_3 + 1;
var INTERSECT_CONIC_QUAD_NO = INTERSECT_CONIC_QUAD_4 + 1;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var INTERSECT_CONIC = INTERSECT_CONIC_QUAD_NO + 1;
var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
// FIXME: add cubic 5- 9
var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
var SORT_BINARY = SORT_UNARY + 1;
var OP_DIFFERENCE = SORT_BINARY + 1;
var OP_INTERSECT = OP_DIFFERENCE + 1;
var OP_UNION = OP_INTERSECT + 1;
var OP_XOR = OP_UNION + 1;
var MARK_LINE = OP_XOR + 1;
var MARK_QUAD = MARK_LINE + 1;
var MARK_CONIC = MARK_QUAD + 1;
var MARK_CUBIC = MARK_CONIC + 1;
var MARK_DONE_LINE = MARK_CUBIC + 1;
var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
var ANGLE_AFTER = COMPUTED_SET_2 + 1;
var ANGLE_AFTERPART = ANGLE_AFTER + 1;
var ACTIVE_OP = ANGLE_AFTERPART + 1;
var COIN_MAIN_SPAN = ACTIVE_OP + 1;
var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1;
var FRAG_TYPE_LAST = COIN_OPP_SPAN;
var REC_TYPE_UNKNOWN = -1;
var REC_TYPE_PATH = 0;
var REC_TYPE_PATH2 = 1;
var REC_TYPE_SECT = 2;
var REC_TYPE_ACTIVE = 3;
var REC_TYPE_ADD = 4;
var REC_TYPE_SORT = 5;
var REC_TYPE_OP = 6;
var REC_TYPE_MARK = 7;
var REC_TYPE_COMPUTED = 8;
var REC_TYPE_COIN = 9;
var REC_TYPE_ANGLE = 10;
var REC_TYPE_ACTIVE_OP = 11;
var REC_TYPE_AFTERPART = 12;
var REC_TYPE_TOP = 13;
var REC_TYPE_COINCIDENCE = 14;
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
var REC_TYPE_ALIGNED = 15;
var REC_TYPE_LAST = REC_TYPE_ALIGNED;
function strs_to_nums(strs) {
var result = [];
for (var idx = 1; idx < strs.length; ++idx) {
var str = strs[idx];
var num = parseFloat(str);
if (isNaN(num)) {
result.push(str);
} else {
result.push(num);
}
}
return result;
}
function filter_str_by(id, str, regex, array) {
if (regex.test(str)) {
var strs = regex.exec(str);
var result = strs_to_nums(strs);
array.push(id);
array.push(result);
return true;
}
return false;
}
function construct_regexp2(pattern) {
var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)");
escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
escape = escape.replace(/PATH/g, "pathB?");
escape = escape.replace(/IDX/g, "(-?\\d+)");
escape = escape.replace(/NUM/g, "(-?\\d+)");
escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
return new RegExp(escape, 'i');
}
function construct_regexp2c(pattern) {
var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)");
escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?");
escape = escape.replace(/OPER/g, "[a-z]+");
escape = escape.replace(/PATH/g, "pathB?");
escape = escape.replace(/T_F/g, "([TF])");
escape = escape.replace(/IDX/g, "(-?\\d+)");
escape = escape.replace(/NUM/g, "(-?\\d+)");
escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
return new RegExp(escape, 'i');
}
function match_regexp(str, lineNo, array, id, pattern) {
var regex = construct_regexp2(pattern);
if (filter_str_by(id, str, regex, array)) {
return true;
}
regex = construct_regexp2c(pattern);
return filter_str_by(id, str, regex, array);
}
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
function parse_all(test) {
var lines = test.match(/[^\r\n]+/g);
var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
var record = [];
var recType = REC_TYPE_UNKNOWN;
var lastLineNo;
var moveX, moveY;
for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
var line = lines[lineNo];
if (line.length == 0) {
continue;
}
var opStart = "SkOpSegment::";
if (line.lastIndexOf(opStart, 0) === 0) {
line = line.substr(opStart.length);
}
var angleStart = "SkOpAngle::";
if (line.lastIndexOf(angleStart, 0) === 0) {
line = line.substr(angleStart.length);
}
var coinStart = "SkOpCoincidence::";
if (line.lastIndexOf(coinStart, 0) === 0) {
line = line.substr(coinStart.length);
}
var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
: line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE
: line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
: line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
: line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
: line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
: line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
: line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
: line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
: line.lastIndexOf("aligned=", 0) === 0 ? REC_TYPE_ALIGNED
: line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
: line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
: line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
: line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
: line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
: line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
: line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
: line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
: line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
: line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
: REC_TYPE_UNKNOWN;
if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
|| recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
if (recType != REC_TYPE_UNKNOWN) {
records.push(recType);
records.push(lastLineNo);
records.push(record);
}
record = [];
recType = type;
lastLineNo = lineNo;
}
var found = false;
switch (recType) {
case REC_TYPE_ACTIVE:
found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
);
break;
case REC_TYPE_ACTIVE_OP:
found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
);
break;
case REC_TYPE_ADD:
if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
moveX = record[1][0];
moveY = record[1][1];
found = true;
} else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
record[1].unshift(moveY);
record[1].unshift(moveX);
moveX = record[1][2];
moveY = record[1][3];
found = true;
} else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
record[1].unshift(moveY);
record[1].unshift(moveX);
moveX = record[1][4];
moveY = record[1][5];
found = true;
} else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
record[1].unshift(moveY);
record[1].unshift(moveX);
moveX = record[1][4];
moveY = record[1][5];
found = true;
} else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
record[1].unshift(moveY);
record[1].unshift(moveX);
moveX = record[1][6];
moveY = record[1][7];
found = true;
} else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
found = true;
} else {
found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
}
break;
case REC_TYPE_AFTERPART:
found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL id=IDX")
|| match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL id=IDX")
|| match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL id=IDX")
|| match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL id=IDX")
break;
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
case REC_TYPE_ALIGNED:
found = match_regexp(line, lineNo, record, PATH_LINE, "aligned=IDX LINE_VAL"
) || match_regexp(line, lineNo, record, PATH_QUAD, "aligned=IDX QUAD_VAL"
) || match_regexp(line, lineNo, record, PATH_CONIC, "aligned=IDX CONIC_VAL"
) || match_regexp(line, lineNo, record, PATH_CUBIC, "aligned=IDX CUBIC_VAL"
);
break;
case REC_TYPE_ANGLE:
found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
"[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");
break;
case REC_TYPE_COIN:
found = true;
break;
case REC_TYPE_COINCIDENCE:
found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" +
" + id=IDX t=T_VAL tEnd=T_VAL"
) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" +
" - id=IDX t=T_VAL tEnd=T_VAL"
);
break;
case REC_TYPE_COMPUTED:
found = line == "computed quadratics given"
|| match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
);
break;
case REC_TYPE_PATH:
found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
);
break;
case REC_TYPE_PATH2:
found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
);
break;
case REC_TYPE_SECT:
found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
" no intersect LINE_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
" no intersect QUAD_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
" no intersect QUAD_VAL QUAD_VAL"
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
" no intersect CONIC_VAL LINE_VAL"
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD, "debugShowConicQuadIntersection" +
" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_2, "debugShowConicQuadIntersection" +
" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_3, "debugShowConicQuadIntersection" +
" 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"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_4, "debugShowConicQuadIntersection" +
" 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"
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_NO, "debugShowConicQuadIntersection" +
" no intersect CONIC_VAL QUAD_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
" no intersect CONIC_VAL CONIC_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
" 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"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
" no intersect CUBIC_VAL LINE_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
" 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"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
" 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"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
" no intersect CUBIC_VAL QUAD_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
" 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"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
" 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"
) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
" no intersect CUBIC_VAL CUBIC_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
" no self intersect CUBIC_VAL"
);
break;
case REC_TYPE_SORT:
var hasDone = / done/.test(line);
var hasUnorderable = / unorderable/.test(line);
var hasSmall = / small/.test(line);
var hasTiny = / tiny/.test(line);
var hasOperand = / operand/.test(line);
var hasStop = / stop/.test(line);
line.replace(/[ a-z]+$/, "");
found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
" [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"
) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
" [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"
);
if (found) {
record[1].push(hasDone);
record[1].push(hasUnorderable);
record[1].push(hasSmall);
record[1].push(hasTiny);
record[1].push(hasOperand);
record[1].push(hasStop);
}
break;
case REC_TYPE_TOP:
found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
);
break;
case REC_TYPE_MARK:
found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
" 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"
) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
" 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"
) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
" 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"
) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
" 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"
) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
" last segment=IDX span=IDX"
) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
" last seg=IDX span=IDX"
) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
" last segment=IDX span=IDX windSum=OPT"
) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
" last seg=IDX span=IDX windSum=OPT"
);
break;
case REC_TYPE_OP:
if (line.lastIndexOf("oppSign oppSign=", 0) === 0
|| line.lastIndexOf("operator<", 0) === 0) {
found = true;
break;
}
found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
) || match_regexp(line, lineNo, record, OP_UNION, "op union"
) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
);
break;
case REC_TYPE_UNKNOWN:
found = true;
break;
}
if (!found) {
console.log(line + " [" + lineNo + "] of type " + type + " not found");
}
}
if (recType != REC_TYPE_UNKNOWN) {
records.push(recType);
records.push(lastLineNo);
records.push(record);
}
if (records.length >= 1) {
tests[testIndex] = records;
testLines[testIndex] = lines;
}
}
function init(test) {
var canvas = document.getElementById('canvas');
if (!canvas.getContext) return;
ctx = canvas.getContext('2d');
var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
var unscaledWidth = window.innerWidth - 20;
var unscaledHeight = window.innerHeight - 20;
screenWidth = unscaledWidth;
screenHeight = unscaledHeight;
canvas.width = unscaledWidth * resScale;
canvas.height = unscaledHeight * resScale;
canvas.style.width = unscaledWidth + 'px';
canvas.style.height = unscaledHeight + 'px';
if (resScale != 1) {
ctx.scale(resScale, resScale);
}
xmin = Infinity;
xmax = -Infinity;
ymin = Infinity;
ymax = -Infinity;
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
hasPath = hasAlignedPath = hasComputedPath = false;
firstActiveSpan = -1;
for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
var recType = test[tIndex];
if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
console.log("unknown rec type: " + recType);
throw "stop execution";
}
var records = test[tIndex + 2];
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
console.log("unknown in range frag type: " + fragType);
throw "stop execution";
}
var frags = records[recordIndex + 1];
var first = 0;
var last = -1;
var first2 = 0;
var last2 = 0;
switch (recType) {
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
case REC_TYPE_ALIGNED:
hasAlignedPath = true;
case REC_TYPE_COMPUTED:
if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
break;
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
if (REC_TYPE_COMPUTED == recType) {
hasComputedPath = true;
}
case REC_TYPE_PATH:
first = 1;
switch (fragType) {
case PATH_LINE:
last = 5;
break;
case PATH_CONIC:
case PATH_QUAD:
last = 7;
break;
case PATH_CUBIC:
last = 9;
break;
default:
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
: "REC_TYPE_COMPUTED") + " frag type:" + fragType);
throw "stop execution";
}
if (recType == REC_TYPE_PATH) {
hasPath = true;
}
break;
case REC_TYPE_PATH2:
first = 1;
switch (fragType) {
case PATH_LINE:
last = 5;
break;
case PATH_CONIC:
case PATH_QUAD:
last = 7;
break;
case PATH_CUBIC:
last = 9;
break;
default:
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
: "REC_TYPE_COMPUTED") + " frag type:" + fragType);
throw "stop execution";
}
if (recType == REC_TYPE_PATH2) {
hasPath = true;
}
break;
case REC_TYPE_ACTIVE:
if (firstActiveSpan < 0) {
firstActiveSpan = tIndex;
}
first = 1;
switch (fragType) {
case ACTIVE_LINE_SPAN:
last = 5;
break;
case ACTIVE_CONIC_SPAN:
case ACTIVE_QUAD_SPAN:
last = 7;
break;
case ACTIVE_CUBIC_SPAN:
last = 9;
break;
default:
console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_ADD:
switch (fragType) {
case ADD_MOVETO:
break;
case ADD_LINETO:
last = 4;
break;
case ADD_CONICTO:
case ADD_QUADTO:
last = 6;
break;
case ADD_CUBICTO:
last = 8;
break;
case ADD_CLOSE:
case ADD_FILL:
break;
default:
console.log("unknown REC_TYPE_ADD frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_AFTERPART:
switch (fragType) {
case PATH_LINE:
last = 4;
break;
case PATH_CONIC:
case PATH_QUAD:
last = 6;
break;
case PATH_CUBIC:
last = 8;
break;
default:
console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_SECT:
switch (fragType) {
case INTERSECT_LINE:
first = 1; last = 5; first2 = 8; last2 = 12;
break;
case INTERSECT_LINE_2:
first = 1; last = 5; first2 = 11; last2 = 15;
break;
case INTERSECT_LINE_NO:
first = 0; last = 4; first2 = 4; last2 = 8;
break;
case INTERSECT_CONIC_LINE:
first = 1; last = 7; first2 = 11; last2 = 15;
break;
case INTERSECT_QUAD_LINE:
first = 1; last = 7; first2 = 10; last2 = 14;
break;
case INTERSECT_CONIC_LINE_2:
first = 1; last = 7; first2 = 14; last2 = 18;
break;
case INTERSECT_QUAD_LINE_2:
first = 1; last = 7; first2 = 13; last2 = 17;
break;
case INTERSECT_CONIC_LINE_NO:
first = 0; last = 6; first2 = 7; last2 = 11;
break;
case INTERSECT_QUAD_LINE_NO:
first = 0; last = 6; first2 = 6; last2 = 10;
break;
case INTERSECT_CONIC:
first = 1; last = 7; first2 = 11; last2 = 17;
break;
case INTERSECT_QUAD:
first = 1; last = 7; first2 = 10; last2 = 16;
break;
case INTERSECT_CONIC_2:
first = 1; last = 7; first2 = 14; last2 = 20;
break;
case INTERSECT_QUAD_2:
first = 1; last = 7; first2 = 13; last2 = 19;
break;
case INTERSECT_CONIC_NO:
first = 0; last = 6; first2 = 7; last2 = 13;
break;
case INTERSECT_QUAD_NO:
first = 0; last = 6; first2 = 6; last2 = 12;
break;
case INTERSECT_SELF_CUBIC:
first = 1; last = 9;
break;
case INTERSECT_SELF_CUBIC_NO:
first = 0; last = 8;
break;
case INTERSECT_CUBIC_LINE:
first = 1; last = 9; first2 = 12; last2 = 16;
break;
case INTERSECT_CUBIC_LINE_2:
first = 1; last = 9; first2 = 15; last2 = 19;
break;
case INTERSECT_CUBIC_LINE_3:
first = 1; last = 9; first2 = 18; last2 = 22;
break;
case INTERSECT_CUBIC_LINE_NO:
first = 0; last = 8; first2 = 8; last2 = 12;
break;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD:
first = 1; last = 7; first2 = 11; last2 = 17;
break;
case INTERSECT_CONIC_QUAD_2:
first = 1; last = 7; first2 = 14; last2 = 20;
break;
case INTERSECT_CONIC_QUAD_3:
first = 1; last = 7; first2 = 17; last2 = 23;
break;
case INTERSECT_CONIC_QUAD_4:
first = 1; last = 7; first2 = 20; last2 = 26;
break;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD_NO:
first = 0; last = 6; first2 = 7; last2 = 13;
break;
case INTERSECT_CUBIC_QUAD:
first = 1; last = 9; first2 = 12; last2 = 18;
break;
case INTERSECT_CUBIC_QUAD_2:
first = 1; last = 9; first2 = 15; last2 = 21;
break;
case INTERSECT_CUBIC_QUAD_3:
first = 1; last = 9; first2 = 18; last2 = 24;
break;
case INTERSECT_CUBIC_QUAD_4:
first = 1; last = 9; first2 = 21; last2 = 27;
break;
case INTERSECT_CUBIC_QUAD_NO:
first = 0; last = 8; first2 = 8; last2 = 14;
break;
case INTERSECT_CUBIC:
first = 1; last = 9; first2 = 12; last2 = 20;
break;
case INTERSECT_CUBIC_2:
first = 1; last = 9; first2 = 15; last2 = 23;
break;
case INTERSECT_CUBIC_3:
first = 1; last = 9; first2 = 18; last2 = 26;
break;
case INTERSECT_CUBIC_4:
first = 1; last = 9; first2 = 21; last2 = 29;
break;
case INTERSECT_CUBIC_NO:
first = 0; last = 8; first2 = 8; last2 = 16;
break;
default:
console.log("unknown REC_TYPE_SECT frag type: " + fragType);
throw "stop execution";
}
break;
default:
continue;
}
for (var idx = first; idx < last; idx += 2) {
xmin = Math.min(xmin, frags[idx]);
xmax = Math.max(xmax, frags[idx]);
ymin = Math.min(ymin, frags[idx + 1]);
ymax = Math.max(ymax, frags[idx + 1]);
}
for (var idx = first2; idx < last2; idx += 2) {
xmin = Math.min(xmin, frags[idx]);
xmax = Math.max(xmax, frags[idx]);
ymin = Math.min(ymin, frags[idx + 1]);
ymax = Math.max(ymax, frags[idx + 1]);
}
}
}
var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
var recType = test[tIndex];
var records = test[tIndex + 2];
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
var frags = records[recordIndex + 1];
switch (recType) {
case REC_TYPE_ACTIVE_OP:
if (!draw_op) {
break;
}
{
var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
curve_extremes(curve, angleBounds);
}
break;
case REC_TYPE_ANGLE:
if (!draw_angle) {
break;
}
{
var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
curve_extremes(curve, angleBounds);
curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
curve_extremes(curve, angleBounds);
curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
}
break;
case REC_TYPE_COINCIDENCE:
if (!draw_coincidence) {
break;
}
{
var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
curve_extremes(curve, angleBounds);
}
break;
case REC_TYPE_SORT:
if (!draw_sort) {
break;
}
if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
curve_extremes(curve, angleBounds);
}
break;
case REC_TYPE_TOP:
if (!draw_top) {
break;
}
{
var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
curve_extremes(curve, angleBounds);
}
break;
}
}
}
xmin = Math.min(xmin, angleBounds[0]);
ymin = Math.min(ymin, angleBounds[1]);
xmax = Math.max(xmax, angleBounds[2]);
ymax = Math.max(ymax, angleBounds[3]);
setScale(xmin, xmax, ymin, ymax);
if (hasPath == false && hasComputedPath == true && !draw_computed) {
draw_computed = 7; // show quadratics, conics, and cubics
}
if (hasPath == true && hasComputedPath == false && draw_computed) {
draw_computed = 0;
}
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
function curveByIDMatch(test, id, recMatch) {
var tIndex = -3;
while ((tIndex += 3) < test.length) {
var recType = test[tIndex];
if (recType == REC_TYPE_OP) {
continue;
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
if (recType != recMatch) {
return [];
}
var records = test[tIndex + 2];
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
var frags = records[recordIndex + 1];
if (frags[0] == id) {
switch (fragType) {
case PATH_LINE:
return [frags[1], frags[2], frags[3], frags[4]];
case PATH_QUAD:
return [frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6]];
case PATH_CONIC:
return [frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7]];
case PATH_CUBIC:
return [frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], frags[8]];
}
}
}
}
return [];
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
function curveByID(test, id) {
var result = draw_path >= 4 ? curveByIDMatch(test, id, REC_TYPE_ALIGNED) : [];
if (!result.length) {
result = curveByIDMatch(test, id, REC_TYPE_PATH);
}
return result;
}
function curvePartialByIDMatch(test, id, t0, t1, recMatch) {
var tIndex = -3;
while ((tIndex += 3) < test.length) {
var recType = test[tIndex];
if (recType == REC_TYPE_OP) {
continue;
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
if (recType != recMatch) {
return [];
}
var records = test[tIndex + 2];
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
var frags = records[recordIndex + 1];
if (frags[0] == id) {
switch (fragType) {
case PATH_LINE:
return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
case PATH_QUAD:
return quadPartial(frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], t0, t1);
case PATH_CONIC:
return conicPartial(frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], t0, t1);
case PATH_CUBIC:
return cubicPartial(frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], frags[8], t0, t1);
}
}
}
}
return [];
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
function curvePartialByID(test, id, t0, t1) {
var result = draw_path >= 4 ? curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_ALIGNED) : [];
if (!result.length) {
result = curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_PATH);
}
return result;
}
function idByCurveIDMatch(test, frag, type, recMatch) {
var tIndex = 0;
while (tIndex < test.length) {
var recType = test[tIndex];
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
if (recType != recMatch) {
++tIndex;
continue;
}
var records = test[tIndex + 2];
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
var frags = records[recordIndex + 1];
if (frag.length != frags.length - 1) {
continue;
}
switch (fragType) {
case PATH_LINE:
if (frag[0] != frags[1] || frag[1] != frags[2]
|| frag[2] != frags[3] || frag[3] != frags[4]) {
continue;
}
return frags[0];
case PATH_QUAD:
if (frag[0] != frags[1] || frag[1] != frags[2]
|| frag[2] != frags[3] || frag[3] != frags[4]
|| frag[4] != frags[5] || frag[5] != frags[6]) {
continue;
}
return frags[0];
case PATH_CONIC:
if (frag[0] != frags[1] || frag[1] != frags[2]
|| frag[2] != frags[3] || frag[3] != frags[4]
|| frag[4] != frags[5] || frag[5] != frags[6]
|| frag[6] != frags[7]) {
continue;
}
return frags[0];
case PATH_CUBIC:
if (frag[0] != frags[1] || frag[1] != frags[2]
|| frag[2] != frags[3] || frag[3] != frags[4]
|| frag[4] != frags[5] || frag[5] != frags[6]
|| frag[6] != frags[7] || frag[7] != frags[8]) {
continue;
}
return frags[0];
}
}
++tIndex;
}
return -1;
}
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
function idByCurve(test, frag, type) {
var result = draw_path >= 4 ? idByCurveIDMatch(test, frag, type, REC_TYPE_ALIGNED) : [];
if (!result.length) {
result = idByCurveIDMatch(test, frag, type, REC_TYPE_PATH);
}
return result;
}
function curve_extremes(curve, bounds) {
var length = curve.length == 7 ? 6 : curve.length;
for (var index = 0; index < length; index += 2) {
var x = curve[index];
var y = curve[index + 1];
bounds[0] = Math.min(bounds[0], x);
bounds[1] = Math.min(bounds[1], y);
bounds[2] = Math.max(bounds[2], x);
bounds[3] = Math.max(bounds[3], y);
}
}
function setScale(x0, x1, y0, y1) {
var srcWidth = x1 - x0;
var srcHeight = y1 - y0;
var usableWidth = screenWidth;
var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
usableWidth -= (xDigits + yDigits) * 10;
usableWidth -= decimal_places * 10;
if (draw_legend) {
usableWidth -= 40;
}
var hscale = usableWidth / srcWidth;
var vscale = screenHeight / srcHeight;
scale = Math.min(hscale, vscale);
var invScale = 1 / scale;
var sxmin = x0 - invScale * 5;
var symin = y0 - invScale * 10;
var sxmax = x1 + invScale * (6 * decimal_places + 10);
var symax = y1 + invScale * 10;
srcWidth = sxmax - sxmin;
srcHeight = symax - symin;
hscale = usableWidth / srcWidth;
vscale = screenHeight / srcHeight;
scale = Math.min(hscale, vscale);
srcLeft = sxmin;
srcTop = symin;
}
function drawArc(curve, op, from, to) {
var type = PATH_LINE + (curve.length / 2 - 2);
var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
var dy = pt.y - curve[1];
var dx = pt.x - curve[0];
var dist = Math.sqrt(dy * dy + dx * dx);
var _dist = dist * scale;
var angle = Math.atan2(dy, dx);
var _px = (curve[0] - srcLeft) * scale;
var _py = (curve[1] - srcTop) * scale;
var divisor = 4;
var endDist;
do {
var ends = [];
for (var index = -1; index <= 1; index += 2) {
var px = Math.cos(index * Math.PI / divisor);
var py = Math.sin(index * Math.PI / divisor);
ends.push(px);
ends.push(py);
}
var endDx = (ends[2] - ends[0]) * scale * dist;
var endDy = (ends[3] - ends[1]) * scale * dist;
endDist = Math.sqrt(endDx * endDx + endDy * endDy);
if (endDist < 100) {
break;
}
divisor *= 2;
} while (true);
if (endDist < 30) {
return;
}
if (op) {
divisor *= 2;
}
ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
ctx.beginPath();
ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
ctx.stroke();
var saveAlign = ctx.textAlign;
var saveStyle = ctx.fillStyle;
var saveFont = ctx.font;
ctx.textAlign = "center";
ctx.fillStyle = "black";
ctx.font = "normal 24px Arial";
divisor *= 0.8;
for (var index = -1; index <= 1; index += 2) {
var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
var _px = (px - srcLeft) * scale;
var _py = (py - srcTop) * scale;
ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
}
ctx.textAlign = saveAlign;
ctx.fillStyle = saveStyle;
ctx.font = saveFont;
}
function drawPoint(px, py, end) {
var length = drawnPts.length == 7 ? 6 : drawnPts.length;
for (var pts = 0; pts < length; pts += 2) {
var x = drawnPts[pts];
var y = drawnPts[pts + 1];
if (px == x && py == y) {
return;
}
}
drawnPts.push(px);
drawnPts.push(py);
var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
var _px = (px - srcLeft) * scale;
var _py = (py - srcTop) * scale;
ctx.beginPath();
ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
ctx.closePath();
if (end) {
ctx.fill();
} else {
ctx.stroke();
}
if (debug_xy) {
ctx.textAlign = "left";
ctx.fillText(label, _px + 5, _py);
}
}
function coordCount(curveType) {
switch (curveType) {
case PATH_LINE:
return 4;
case PATH_QUAD:
return 6;
case PATH_CONIC:
return 6;
case PATH_CUBIC:
return 8;
}
return -1;
}
function drawPoints(ptArray, curveType, drawControls) {
var count = coordCount(curveType);
for (var idx = 0; idx < count; idx += 2) {
if (!drawControls && idx != 0 && idx != count - 2) {
continue;
}
drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
}
}
function drawControlLines(curve, curveType, drawEnd) {
if (curveType == PATH_LINE) {
return;
}
ctx.strokeStyle = "rgba(0,0,0, 0.3)";
drawLine(curve[0], curve[1], curve[2], curve[3]);
drawLine(curve[2], curve[3], curve[4], curve[5]);
if (curveType == PATH_CUBIC) {
drawLine(curve[4], curve[5], curve[6], curve[7]);
if (drawEnd > 1) {
drawLine(curve[6], curve[7], curve[0], curve[1]);
if (drawEnd > 2) {
drawLine(curve[0], curve[1], curve[4], curve[5]);
drawLine(curve[6], curve[7], curve[2], curve[3]);
}
}
} else if (drawEnd > 1) {
drawLine(curve[4], curve[5], curve[0], curve[1]);
}
}
function pointAtT(curve, curveType, t) {
var xy = {};
switch (curveType) {
case PATH_LINE:
var a = 1 - t;
var b = t;
xy.x = a * curve[0] + b * curve[2];
xy.y = a * curve[1] + b * curve[3];
break;
case PATH_QUAD:
var one_t = 1 - t;
var a = one_t * one_t;
var b = 2 * one_t * t;
var c = t * t;
xy.x = a * curve[0] + b * curve[2] + c * curve[4];
xy.y = a * curve[1] + b * curve[3] + c * curve[5];
break;
case PATH_CONIC:
var one_t = 1 - t;
var a = one_t * one_t;
var b = 2 * one_t * t;
var c = t * t;
xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
var d = a + b * curve[6] + c;
xy.x /= d;
xy.y /= d;
break;
case PATH_CUBIC:
var one_t = 1 - t;
var one_t2 = one_t * one_t;
var a = one_t2 * one_t;
var b = 3 * one_t2 * t;
var t2 = t * t;
var c = 3 * one_t * t2;
var d = t2 * t;
xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
break;
}
return xy;
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawPointAtT(curve, curveType) {
var x, y;
var xy = pointAtT(curve, curveType, curveT);
drawPoint(xy.x, xy.y, true);
if (!draw_intersectT) {
return;
}
ctx.fillStyle = "red";
drawTAtPointUp(xy.x, xy.y, curveT);
}
function drawTAtPointUp(px, py, t) {
var label = t.toFixed(decimal_places);
var _px = (px - srcLeft)* scale;
var _py = (py - srcTop) * scale;
ctx.fillText(label, _px + 5, _py - 10);
}
function drawTAtPointDown(px, py, t) {
var label = t.toFixed(decimal_places);
var _px = (px - srcLeft)* scale;
var _py = (py - srcTop) * scale;
ctx.fillText(label, _px + 5, _py + 10);
}
function alreadyDrawnLine(x1, y1, x2, y2) {
if (collect_bounds) {
if (focus_enabled) {
focusXmin = Math.min(focusXmin, x1, x2);
focusYmin = Math.min(focusYmin, y1, y2);
focusXmax = Math.max(focusXmax, x1, x2);
focusYmax = Math.max(focusYmax, y1, y2);
}
return true;
}
for (var pts = 0; pts < drawnLines.length; pts += 4) {
if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
&& x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
return true;
}
}
drawnLines.push(x1);
drawnLines.push(y1);
drawnLines.push(x2);
drawnLines.push(y2);
return false;
}
function drawLine(x1, y1, x2, y2) {
if (alreadyDrawnLine(x1, y1, x2, y2)) {
return;
}
ctx.beginPath();
ctx.moveTo((x1 - srcLeft) * scale,
(y1 - srcTop) * scale);
ctx.lineTo((x2 - srcLeft) * scale,
(y2 - srcTop) * scale);
ctx.stroke();
}
function linePartial(x1, y1, x2, y2, t1, t2) {
var dx = x1 - x2;
var dy = y1 - y2;
var array = [
x1 - t1 * dx,
y1 - t1 * dy,
x1 - t2 * dx,
y1 - t2 * dy
];
return array;
}
function drawLinePartial(x1, y1, x2, y2, t1, t2) {
var a = linePartial(x1, y1, x2, y2, t1, t2);
var ax = a[0];
var ay = a[1];
var bx = a[2];
var by = a[3];
if (alreadyDrawnLine(ax, ay, bx, by)) {
return;
}
ctx.beginPath();
ctx.moveTo((ax - srcLeft) * scale,
(ay - srcTop) * scale);
ctx.lineTo((bx - srcLeft) * scale,
(by - srcTop) * scale);
ctx.stroke();
}
function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
if (collect_bounds) {
if (focus_enabled) {
focusXmin = Math.min(focusXmin, x1, x2, x3);
focusYmin = Math.min(focusYmin, y1, y2, y3);
focusXmax = Math.max(focusXmax, x1, x2, x3);
focusYmax = Math.max(focusYmax, y1, y2, y3);
}
return true;
}
for (var pts = 0; pts < drawnQuads.length; pts += 6) {
if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
&& x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
&& x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
return true;
}
}
drawnQuads.push(x1);
drawnQuads.push(y1);
drawnQuads.push(x2);
drawnQuads.push(y2);
drawnQuads.push(x3);
drawnQuads.push(y3);
return false;
}
function drawQuad(x1, y1, x2, y2, x3, y3) {
if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
return;
}
ctx.beginPath();
ctx.moveTo((x1 - srcLeft) * scale,
(y1 - srcTop) * scale);
ctx.quadraticCurveTo((x2 - srcLeft) * scale,
(y2 - srcTop) * scale,
(x3 - srcLeft) * scale,
(y3 - srcTop) * scale);
ctx.stroke();
}
function interp(A, B, t) {
return A + (B - A) * t;
}
function interp_quad_coords(x1, x2, x3, t)
{
var ab = interp(x1, x2, t);
var bc = interp(x2, x3, t);
var abc = interp(ab, bc, t);
return abc;
}
function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
var ax = interp_quad_coords(x1, x2, x3, t1);
var ay = interp_quad_coords(y1, y2, y3, t1);
var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
var cx = interp_quad_coords(x1, x2, x3, t2);
var cy = interp_quad_coords(y1, y2, y3, t2);
var bx = 2*dx - (ax + cx)/2;
var by = 2*dy - (ay + cy)/2;
var array = [
ax, ay, bx, by, cx, cy
];
return array;
}
function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
var ax = a[0];
var ay = a[1];
var bx = a[2];
var by = a[3];
var cx = a[4];
var cy = a[5];
if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
return;
}
ctx.beginPath();
ctx.moveTo((ax - srcLeft) * scale,
(ay - srcTop) * scale);
ctx.quadraticCurveTo((bx - srcLeft) * scale,
(by - srcTop) * scale,
(cx - srcLeft) * scale,
(cy - srcTop) * scale);
ctx.stroke();
}
function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
if (collect_bounds) {
if (focus_enabled) {
focusXmin = Math.min(focusXmin, x1, x2, x3);
focusYmin = Math.min(focusYmin, y1, y2, y3);
focusXmax = Math.max(focusXmax, x1, x2, x3);
focusYmax = Math.max(focusYmax, y1, y2, y3);
}
return true;
}
for (var pts = 0; pts < drawnConics.length; pts += 8) {
if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
&& x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
&& x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
&& w == drawnCubics[pts + 6]) {
return true;
}
}
drawnConics.push(x1);
drawnConics.push(y1);
drawnConics.push(x2);
drawnConics.push(y2);
drawnConics.push(x3);
drawnConics.push(y3);
drawnCubics.push(w);
return false;
}
var kMaxConicToQuadPOW2 = 5;
function computeQuadPOW2(curve, tol) {
var a = curve[6] - 1;
var k = a / (4 * (2 + a));
var x = k * (curve[0] - 2 * curve[2] + curve[4]);
var y = k * (curve[1] - 2 * curve[3] + curve[5]);
var error = Math.sqrt(x * x + y * y);
var pow2;
for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
if (error <= tol) {
break;
}
error *= 0.25;
}
return pow2;
}
function subdivide_w_value(w) {
return Math.sqrt(0.5 + w * 0.5);
}
function chop(curve, part1, part2) {
var w = curve[6];
var scale = 1 / (1 + w);
part1[0] = curve[0];
part1[1] = curve[1];
part1[2] = (curve[0] + curve[2] * w) * scale;
part1[3] = (curve[1] + curve[3] * w) * scale;
part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
part2[2] = (curve[2] * w + curve[4]) * scale;
part2[3] = (curve[3] * w + curve[5]) * scale;
part2[4] = curve[4];
part2[5] = curve[5];
part1[6] = part2[6] = subdivide_w_value(w);
}
function subdivide(curve, level, pts) {
if (0 == level) {
pts.push(curve[2]);
pts.push(curve[3]);
pts.push(curve[4]);
pts.push(curve[5]);
} else {
var part1 = [], part2 = [];
chop(curve, part1, part2);
--level;
subdivide(part1, level, pts);
subdivide(part2, level, pts);
}
}
function chopIntoQuadsPOW2(curve, pow2, pts) {
subdivide(curve, pow2, pts);
return 1 << pow2;
}
function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
return;
}
ctx.beginPath();
ctx.moveTo((x1 - srcLeft) * scale,
(y1 - srcTop) * scale);
var tol = 1 / scale;
var curve = [x1, y1, x2, y2, x3, y3, w];
var pow2 = computeQuadPOW2(curve, tol);
var pts = [];
chopIntoQuadsPOW2(curve, pow2, pts);
for (var i = 0; i < pts.length; i += 4) {
ctx.quadraticCurveTo(
(pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
(pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
}
ctx.stroke();
}
function conic_eval_numerator(x1, x2, x3, w, t) {
var src2w = x2 * w;
var C = x1;
var A = x3 - 2 * src2w + C;
var B = 2 * (src2w - C);
return (A * t + B) * t + C;
}
function conic_eval_denominator(w, t) {
var B = 2 * (w - 1);
var C = 1;
var A = -B;
return (A * t + B) * t + C;
}
function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
var ax = conic_eval_numerator(x1, x2, x3, w, t1);
var ay = conic_eval_numerator(y1, y2, y3, w, t1);
var az = conic_eval_denominator(w, t1);
var midT = (t1 + t2) / 2;
var dx = conic_eval_numerator(x1, x2, x3, w, midT);
var dy = conic_eval_numerator(y1, y2, y3, w, midT);
var dz = conic_eval_denominator(w, midT);
var cx = conic_eval_numerator(x1, x2, x3, w, t2);
var cy = conic_eval_numerator(y1, y2, y3, w, t2);
var cz = conic_eval_denominator(w, t2);
var bx = 2 * dx - (ax + cx) / 2;
var by = 2 * dy - (ay + cy) / 2;
var bz = 2 * dz - (az + cz) / 2;
var dt = t2 - t1;
var dt_1 = 1 - dt;
var array = [
ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, 0
];
var dMidAC = { x:(array[0] + array[4]) / 2, y:(array[1] + array[5]) / 2 };
var dMid = { x:dx / dz, y:dy / dz };
var dWNumer = { x:dMidAC.x - dMid.x, y:dMidAC.y - dMid.y };
var dWDenom = { x:dMid.x - array[2], y:dMid.y - array[3] };
var partW = Math.sqrt(dWNumer.x * dWNumer.x + dWNumer.y * dWNumer.y)
/ Math.sqrt(dWDenom.x * dWDenom.x + dWDenom.y * dWDenom.y);
array[6] = partW;
return array;
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
var ax = a[0];
var ay = a[1];
var bx = a[2];
var by = a[3];
var cx = a[4];
var cy = a[5];
var w_ = a[6];
drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
}
function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
if (collect_bounds) {
if (focus_enabled) {
focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
}
return true;
}
for (var pts = 0; pts < drawnCubics.length; pts += 8) {
if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
&& x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
&& x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
&& x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
return true;
}
}
drawnCubics.push(x1);
drawnCubics.push(y1);
drawnCubics.push(x2);
drawnCubics.push(y2);
drawnCubics.push(x3);
drawnCubics.push(y3);
drawnCubics.push(x4);
drawnCubics.push(y4);
return false;
}
function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
return;
}
ctx.beginPath();
ctx.moveTo((x1 - srcLeft) * scale,
(y1 - srcTop) * scale);
ctx.bezierCurveTo((x2 - srcLeft) * scale,
(y2 - srcTop) * scale,
(x3 - srcLeft) * scale,
(y3 - srcTop) * scale,
(x4 - srcLeft) * scale,
(y4 - srcTop) * scale);
ctx.stroke();
}
function interp_cubic_coords(x1, x2, x3, x4, t)
{
var ab = interp(x1, x2, t);
var bc = interp(x2, x3, t);
var cd = interp(x3, x4, t);
var abc = interp(ab, bc, t);
var bcd = interp(bc, cd, t);
var abcd = interp(abc, bcd, t);
return abcd;
}
function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
var mx = ex * 27 - ax * 8 - dx;
var my = ey * 27 - ay * 8 - dy;
var nx = fx * 27 - ax - dx * 8;
var ny = fy * 27 - ay - dy * 8;
var bx = (mx * 2 - nx) / 18;
var by = (my * 2 - ny) / 18;
var cx = (nx * 2 - mx) / 18;
var cy = (ny * 2 - my) / 18;
var array = [
ax, ay, bx, by, cx, cy, dx, dy
];
return array;
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
var ax = a[0];
var ay = a[1];
var bx = a[2];
var by = a[3];
var cx = a[4];
var cy = a[5];
var dx = a[6];
var dy = a[7];
if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
return;
}
ctx.beginPath();
ctx.moveTo((ax - srcLeft) * scale,
(ay - srcTop) * scale);
ctx.bezierCurveTo((bx - srcLeft) * scale,
(by - srcTop) * scale,
(cx - srcLeft) * scale,
(cy - srcTop) * scale,
(dx - srcLeft) * scale,
(dy - srcTop) * scale);
ctx.stroke();
}
function drawCurve(c) {
switch (c.length) {
case 4:
drawLine(c[0], c[1], c[2], c[3]);
break;
case 6:
drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
break;
case 7:
drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
break;
case 8:
drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
break;
}
}
function boundsWidth(pts) {
var min = pts[0];
var max = pts[0];
var length = pts.length == 7 ? 6 : pts.length;
for (var idx = 2; idx < length; idx += 2) {
min = Math.min(min, pts[idx]);
max = Math.max(max, pts[idx]);
}
return max - min;
}
function boundsHeight(pts) {
var min = pts[1];
var max = pts[1];
var length = pts.length == 7 ? 6 : pts.length;
for (var idx = 3; idx < length; idx += 2) {
min = Math.min(min, pts[idx]);
max = Math.max(max, pts[idx]);
}
return max - min;
}
function tangent(pts) {
var dx = pts[2] - pts[0];
var dy = pts[3] - pts[1];
if (dx == 0 && dy == 0 && pts.length > 4) {
dx = pts[4] - pts[0];
dy = pts[5] - pts[1];
if (dx == 0 && dy == 0 && pts.length == 8) {
dx = pts[6] - pts[0];
dy = pts[7] - pts[1];
}
}
return Math.atan2(-dy, dx);
}
function hodograph(cubic) {
var hodo = [];
hodo[0] = 3 * (cubic[2] - cubic[0]);
hodo[1] = 3 * (cubic[3] - cubic[1]);
hodo[2] = 3 * (cubic[4] - cubic[2]);
hodo[3] = 3 * (cubic[5] - cubic[3]);
hodo[4] = 3 * (cubic[6] - cubic[4]);
hodo[5] = 3 * (cubic[7] - cubic[5]);
return hodo;
}
function hodograph2(cubic) {
var quad = hodograph(cubic);
var hodo = [];
hodo[0] = 2 * (quad[2] - quad[0]);
hodo[1] = 2 * (quad[3] - quad[1]);
hodo[2] = 2 * (quad[4] - quad[2]);
hodo[3] = 2 * (quad[5] - quad[3]);
return hodo;
}
function quadraticRootsReal(A, B, C, s) {
if (A == 0) {
if (B == 0) {
s[0] = 0;
return C == 0;
}
s[0] = -C / B;
return 1;
}
/* normal form: x^2 + px + q = 0 */
var p = B / (2 * A);
var q = C / A;
var p2 = p * p;
if (p2 < q) {
return 0;
}
var sqrt_D = 0;
if (p2 > q) {
sqrt_D = sqrt(p2 - q);
}
s[0] = sqrt_D - p;
s[1] = -sqrt_D - p;
return 1 + s[0] != s[1];
}
function add_valid_ts(s, realRoots, t) {
var foundRoots = 0;
for (var index = 0; index < realRoots; ++index) {
var tValue = s[index];
if (tValue >= 0 && tValue <= 1) {
for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
if (t[idx2] != tValue) {
t[foundRoots++] = tValue;
}
}
}
}
return foundRoots;
}
function quadraticRootsValidT(a, b, c, t) {
var s = [];
var realRoots = quadraticRootsReal(A, B, C, s);
var foundRoots = add_valid_ts(s, realRoots, t);
return foundRoots != 0;
}
function find_cubic_inflections(cubic, tValues) {
var Ax = src[2] - src[0];
var Ay = src[3] - src[1];
var Bx = src[4] - 2 * src[2] + src[0];
var By = src[5] - 2 * src[3] + src[1];
var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
Ax * By - Ay * Bx, tValues);
}
function dxy_at_t(curve, type, t) {
var dxy = {};
if (type == PATH_LINE) {
dxy.x = curve[2] - curve[0];
dxy.y = curve[3] - curve[1];
} else if (type == PATH_QUAD) {
var a = t - 1;
var b = 1 - 2 * t;
var c = t;
dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
} else if (type == PATH_CONIC) {
var p20x = curve[4] - curve[0];
var p20y = curve[5] - curve[1];
var p10xw = (curve[2] - curve[0]) * curve[6];
var p10yw = (curve[3] - curve[1]) * curve[6];
var coeff0x = curve[6] * p20x - p20x;
var coeff0y = curve[6] * p20y - p20y;
var coeff1x = p20x - 2 * p10xw;
var coeff1y = p20y - 2 * p10yw;
dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
} else if (type == PATH_CUBIC) {
var one_t = 1 - t;
var a = curve[0];
var b = curve[2];
var c = curve[4];
var d = curve[6];
dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
a = curve[1];
b = curve[3];
c = curve[5];
d = curve[7];
dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
}
return dxy;
}
function dpt_at_t(curve, t) {
var type = PATH_LINE + (curve.length / 2 - 2);
return dxy_at_t(curve, type, t);
}
function drawLabel(num, px, py) {
ctx.beginPath();
ctx.arc(px, py, 8, 0, Math.PI*2, true);
ctx.closePath();
ctx.strokeStyle = "rgba(0,0,0, 0.4)";
ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
ctx.stroke();
ctx.fillStyle = "black";
ctx.font = "normal 10px Arial";
// ctx.rotate(0.001);
ctx.fillText(num, px - 2, py + 3);
// ctx.rotate(-0.001);
}
function drawLabelX(ymin, num, loc) {
var px = (loc - srcLeft) * scale;
var py = (ymin - srcTop) * scale - 20;
drawLabel(num, px, py);
}
function drawLabelY(xmin, num, loc) {
var px = (xmin - srcLeft) * scale - 20;
var py = (loc - srcTop) * scale;
drawLabel(num, px, py);
}
function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
ctx.beginPath();
ctx.moveTo(hx, hy - 100);
ctx.lineTo(hx, hy);
ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
ctx.stroke();
ctx.beginPath();
ctx.moveTo(hx, hy);
ctx.lineTo(hx, hy + 100);
ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
ctx.stroke();
ctx.beginPath();
ctx.moveTo(hx - 100, hy);
ctx.lineTo(hx, hy);
ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
ctx.stroke();
ctx.beginPath();
ctx.moveTo(hx, hy);
ctx.lineTo(hx + 100, hy);
ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
ctx.stroke();
}
function scalexy(x, y, mag) {
var length = Math.sqrt(x * x + y * y);
return mag / length;
}
function drawArrow(x, y, dx, dy, s) {
var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
dx *= dscale;
dy *= dscale;
ctx.beginPath();
ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
x += dx;
y += dy;
ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
dx /= 10;
dy /= 10;
ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
ctx.strokeStyle = "rgba(0,75,0, 0.4)";
ctx.stroke();
}
function x_at_t(curve, t) {
var one_t = 1 - t;
if (curve.length == 4) {
return one_t * curve[0] + t * curve[2];
}
var one_t2 = one_t * one_t;
var t2 = t * t;
if (curve.length == 6) {
return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
}
if (curve.length == 7) {
return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
/ (one_t2 +2 * one_t * t * curve[6] + t2);
}
var a = one_t2 * one_t;
var b = 3 * one_t2 * t;
var c = 3 * one_t * t2;
var d = t2 * t;
return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
}
function y_at_t(curve, t) {
var one_t = 1 - t;
if (curve.length == 4) {
return one_t * curve[1] + t * curve[3];
}
var one_t2 = one_t * one_t;
var t2 = t * t;
if (curve.length == 6) {
return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
}
if (curve.length == 7) {
return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
/ (one_t2 +2 * one_t * t * curve[6] + t2);
}
var a = one_t2 * one_t;
var b = 3 * one_t2 * t;
var c = 3 * one_t * t2;
var d = t2 * t;
return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
}
function pt_at_t(curve, t) {
var pt = {};
pt.x = x_at_t(curve, t);
pt.y = y_at_t(curve, t);
return pt;
}
function drawOrder(curve, t, label) {
var px = x_at_t(curve, t);
var py = y_at_t(curve, t);
var _px = (px - srcLeft) * scale;
var _py = (py - srcTop) * scale;
ctx.beginPath();
ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = "white";
ctx.fill();
if (label == 'L') {
ctx.strokeStyle = "rgba(255,0,0, 1)";
ctx.fillStyle = "rgba(255,0,0, 1)";
} else {
ctx.strokeStyle = "rgba(0,0,255, 1)";
ctx.fillStyle = "rgba(0,0,255, 1)";
}
ctx.stroke();
ctx.font = "normal 16px Arial";
ctx.textAlign = "center";
ctx.fillText(label, _px, _py + 5);
ctx.font = "normal 10px Arial";
}
function drawVisibleOrder(curve, label) {
var s = pt_at_t(curve, 0);
var e = pt_at_t(curve, 1);
var sOn = ptOnScreen(s);
var eOn = ptOnScreen(e);
var defaultT = 0.85;
if (sOn && eOn)
return drawOrder(curve, defaultT, label);
if (sOn || eOn) {
if (eOn) {
defaultT = 1 - defaultT;
}
var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
var t = defaultT;
var tries = 16;
do {
var mid = pt_at_t(curve, t);
if (ptOnScreen(mid))
return drawOrder(curve, t, label);
t += step;
step /= 2;
} while (--tries > 0);
drawOrder(curve, defaultT, label);
}
// scattershot until we find a visible point
var denom = 2; // visit odd number num / denom to hit unique pts
var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
do {
for (var numer = 1; numer < denom; numer += 2) {
var t = numer / denom + 0.1;
if (t >= 1) {
break;
}
var mid = pt_at_t(curve, t);
if (ptOnScreen(mid))
return drawOrder(curve, t, label);
}
denom *= 2;
} while (--tries > 0);
drawOrder(curve, defaultT, label);
}
function set_length(pt, newLen) {
var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
var scale = newLen / len;
var newPt = { x: pt.x * scale, y: pt.y * scale };
return newPt;
}
function drawDirection(curve, t) {
var d = dpt_at_t(curve, t);
d = set_length(d, 16);
var pt = localToGlobal(pt_at_t(curve, t));
ctx.beginPath();
ctx.moveTo(pt.x - d.y, pt.y + d.x);
ctx.lineTo(pt.x + d.x, pt.y + d.y);
ctx.lineTo(pt.x + d.y, pt.y - d.x);
ctx.strokeStyle = "rgba(0,75,0, 0.4)";
ctx.stroke();
}
function drawVisibleDirection(curve) {
var s = pt_at_t(curve, 0);
var e = pt_at_t(curve, 1);
var sOn = ptOnScreen(s);
var eOn = ptOnScreen(e);
var defaultT = 0.65;
if (sOn && eOn) {
return drawDirection(curve, defaultT);
}
if (sOn || eOn) {
if (eOn) {
defaultT = 1 - defaultT;
}
var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
var t = defaultT;
var tries = 16;
do {
var mid = pt_at_t(curve, t);
if (ptOnScreen(mid))
return drawDirection(curve, t);
t += step;
step /= 2;
} while (--tries > 0);
drawDirection(curve, defaultT);
}
// scattershot until we find a visible point
var denom = 2; // visit odd number num / denom to hit unique pts
var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
do {
for (var numer = 1; numer < denom; numer += 2) {
var t = numer / denom + 0.1;
if (t >= 1) {
break;
}
var mid = pt_at_t(curve, t);
if (ptOnScreen(mid))
return drawDirection(curve, t);
}
denom *= 2;
} while (--tries > 0);
drawDirection(curve, defaultT);
}
function drawID(curve, t, id) {
var px = x_at_t(curve, t);
var py = y_at_t(curve, t);
var _px = (px - srcLeft) * scale;
var _py = (py - srcTop) * scale;
draw_id_at(id, _px, _py);
}
function localToGlobal(local) {
var global = {};
global.x = (local.x - srcLeft) * scale;
global.y = (local.y - srcTop) * scale;
return global;
}
function ptOnScreen(local) {
var pt = localToGlobal(local);
return 10 <= pt.x && pt.x <= screenWidth - 10
&& 10 <= pt.y && pt.y <= screenHeight - 10;
}
function drawVisibleID(curve, defaultT, id) {
// determine if either or both ends are visible
var s = pt_at_t(curve, 0);
var e = pt_at_t(curve, 1);
var sOn = ptOnScreen(s);
var eOn = ptOnScreen(e);
if (sOn && eOn)
return drawID(curve, defaultT, id);
if (sOn || eOn) {
var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
var t = defaultT;
var tries = 16;
do {
var mid = pt_at_t(curve, t);
if (ptOnScreen(mid))
return drawID(curve, t, id);
t += step;
step /= 2;
} while (--tries > 0);
drawID(curve, defaultT, id);
}
// scattershot until we find a visible point
var denom = 2; // visit odd number num / denom to hit unique pts
var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
do {
for (var numer = 1; numer < denom; numer += 2) {
var t = numer / denom;
var mid = pt_at_t(curve, t);
if (ptOnScreen(mid))
return drawID(curve, t, id);
}
denom *= 2;
} while (--tries > 0);
drawID(curve, defaultT, id);
}
function draw_id_at(id, _px, _py) {
ctx.beginPath();
ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = "white";
ctx.fill();
ctx.strokeStyle = "rgba(127,127,0, 1)";
ctx.fillStyle = "rgba(127,127,0, 1)";
ctx.stroke();
ctx.font = "normal 16px Arial";
ctx.textAlign = "center";
ctx.fillText(id, _px, _py + 5);
ctx.font = "normal 10px Arial";
}
function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
var curve = [x1, y1, x2, y2];
drawCurvePartialID(id, curve, t1, t2);
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawLineID(id, x1, y1, x2, y2) {
drawLinePartialID(id, x1, y1, x2, y2, 0, 1);
}
function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
var curve = [x1, y1, x2, y2, x3, y3];
drawCurvePartialID(id, curve, t1, t2);
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawQuadID(id, x1, y1, x2, y2, x3, y3) {
drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, 0, 1);
}
function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
var curve = [x1, y1, x2, y2, x3, y3, w];
drawCurvePartialID(id, curve, t1, t2);
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawConicID(id, x1, y1, x2, y2, x3, y3, w) {
drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, 0, 1);
}
function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
drawCurvePartialID(id, curve, t1, t2);
}
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
function drawCubicID(id, x1, y1, x2, y2, x3, y3, x4, y4) {
drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, 0, 1);
}
function drawCurvePartialID(id, curve, t1, t2) {
drawVisibleID(curve, (t1 + t2) / 2, id);
}
function drawCurveSpecials(test, curve, type) {
if (pt_labels) {
drawPoints(curve, type, pt_labels == 2);
}
if (control_lines != 0) {
drawControlLines(curve, type, control_lines);
}
if (curve_t) {
drawPointAtT(curve, type);
}
if (draw_midpoint) {
var mid = pointAtT(curve, type, 0.5);
drawPoint(mid.x, mid.y, true);
}
if (draw_id) {
var id = idByCurve(test, curve, type);
if (id >= 0) {
drawVisibleID(curve, 0.5, id);
}
}
if (draw_direction) {
drawVisibleDirection(curve);
}
if (type == PATH_LINE) {
return;
}
if (draw_deriviatives > 0) {
var d = dxy_at_t(curve, type, 0);
drawArrow(curve[0], curve[1], d.x, d.y, 1);
if (draw_deriviatives == 2) {
d = dxy_at_t(curve, type, 1);
if (type == PATH_CUBIC) {
drawArrow(curve[6], curve[7], d.x, d.y, 1);
} else {
drawArrow(curve[4], curve[5], d.x, d.y, 1);
}
}
if (draw_midpoint) {
var mid = pointAtT(curve, type, 0.5);
d = dxy_at_t(curve, type, 0.5);
drawArrow(mid.x, mid.y, d.x, d.y, 1);
}
}
if (type != PATH_CUBIC) {
return;
}
if (draw_sequence) {
var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
for (var i = 0; i < 8; i+= 2) {
drawLabelX(ymin, i >> 1, curve[i]);
}
var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
for (var i = 1; i < 8; i+= 2) {
drawLabelY(xmin, i >> 1, curve[i]);
}
}
}
function logCurves(test) {
for (curves in test) {
var curve = test[curves];
dumpCurve(curve);
}
}
function curveToString(curve) {
var str = "{{";
var length = curve.length == 7 ? 6 : curve.length;
if (curve.length == 7) {
str += "{";
}
for (i = 0; i < length; i += 2) {
str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
if (i < curve.length - 2) {
str += "}, {";
}
}
str += "}";
if (curve.length == 7) {
str += "}, " + curve[6].toFixed(decimal_places);
}
str += "}";
return str;
}
function dumpCurve(curve) {
console.log(curveToString(curve));
}
function draw(test, lines, title) {
ctx.fillStyle = "rgba(0,0,0, 0.1)";
ctx.font = "normal 50px Arial";
ctx.textAlign = "left";
ctx.fillText(title, 50, 50);
ctx.font = "normal 10px Arial";
ctx.lineWidth = "1.001"; "0.999";
var secondPath = test.length;
var closeCount = 0;
logStart = -1;
logRange = 0;
// find last active rec type at this step
var curType = test[0];
var curStep = 0;
var hasOp = false;
var lastActive = 0;
var lastAdd = 0;
var lastCoin = 0;
var lastSect = 0;
var lastSort = 0;
var lastMark = 0;
var lastTop = 0;
activeCount = 0;
addCount = 0;
angleCount = 0;
opCount = 0;
sectCount = 0;
sortCount = 0;
topCount = 0;
markCount = 0;
activeMax = 0;
addMax = 0;
angleMax = 0;
coinMax = 0;
opMax = 0;
sectMax = 0;
sectMax2 = 0;
sortMax = 0;
topMax = 0;
markMax = 0;
lastIndex = test.length - 3;
for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
var recType = test[tIndex];
if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
console.log("unknown rec type: " + recType);
throw "stop execution";
}
// if (curType == recType && curType != REC_TYPE_ADD) {
// continue;
// }
var inStepRange = step_limit == 0 || curStep < step_limit;
curType = recType;
if (recType == REC_TYPE_OP) {
hasOp = true;
continue;
}
if (recType == REC_TYPE_UNKNOWN) {
// these types do not advance step
continue;
}
var bumpStep = false;
var records = test[tIndex + 2];
var fragType = records[0];
if (recType == REC_TYPE_ADD) {
if (records.length != 2) {
console.log("expect only two elements: " + records.length);
throw "stop execution";
}
if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
continue;
}
++addMax;
if (!draw_add || !inStepRange) {
continue;
}
lastAdd = tIndex;
++addCount;
bumpStep = true;
}
if (recType == REC_TYPE_PATH && hasOp) {
secondPath = tIndex;
}
if (recType == REC_TYPE_PATH2 && hasOp) {
secondPath = tIndex;
}
if (recType == REC_TYPE_ACTIVE) {
++activeMax;
if (!draw_active || !inStepRange) {
continue;
}
lastActive = tIndex;
++activeCount;
bumpStep = true;
}
if (recType == REC_TYPE_ACTIVE_OP) {
++opMax;
if (!draw_op || !inStepRange) {
continue;
}
lastOp = tIndex;
++opCount;
bumpStep = true;
}
if (recType == REC_TYPE_AFTERPART) {
if (draw_angle != 3 || !inStepRange) {
continue;
}
lastAngle = tIndex;
++angleCount;
bumpStep = true;
}
if (recType == REC_TYPE_ANGLE) {
++angleMax;
if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
continue;
}
lastAngle = tIndex;
++angleCount;
bumpStep = true;
}
if (recType == REC_TYPE_COINCIDENCE) {
++coinMax;
if (!draw_coincidence || !inStepRange) {
continue;
}
lastCoin = tIndex;
++coinCount;
bumpStep = true;
}
if (recType == REC_TYPE_SECT) {
if (records.length != 2) {
console.log("expect only two elements: " + records.length);
throw "stop execution";
}
++sectMax;
var sectBump = 1;
switch (fragType) {
case INTERSECT_LINE:
case INTERSECT_QUAD_LINE:
case INTERSECT_QUAD:
case INTERSECT_CONIC_LINE:
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD:
case INTERSECT_CONIC:
case INTERSECT_SELF_CUBIC:
case INTERSECT_CUBIC_LINE:
case INTERSECT_CUBIC_QUAD:
case INTERSECT_CUBIC:
sectBump = 1;
break;
case INTERSECT_LINE_2:
case INTERSECT_QUAD_LINE_2:
case INTERSECT_QUAD_2:
case INTERSECT_CONIC_LINE_2:
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD_2:
case INTERSECT_CONIC_2:
case INTERSECT_CUBIC_LINE_2:
case INTERSECT_CUBIC_QUAD_2:
case INTERSECT_CUBIC_2:
sectBump = 2;
break;
case INTERSECT_LINE_NO:
case INTERSECT_QUAD_LINE_NO:
case INTERSECT_QUAD_NO:
case INTERSECT_CONIC_LINE_NO:
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD_NO:
case INTERSECT_CONIC_NO:
case INTERSECT_SELF_CUBIC_NO:
case INTERSECT_CUBIC_LINE_NO:
case INTERSECT_CUBIC_QUAD_NO:
case INTERSECT_CUBIC_NO:
sectBump = 0;
break;
case INTERSECT_CONIC_QUAD_3:
case INTERSECT_CUBIC_LINE_3:
case INTERSECT_CUBIC_QUAD_3:
case INTERSECT_CUBIC_3:
sectBump = 3;
break;
case INTERSECT_CONIC_QUAD_4:
case INTERSECT_CUBIC_QUAD_4:
case INTERSECT_CUBIC_4:
sectBump = 4;
break;
default:
console.log("missing case " + records.length);
throw "stop execution";
}
sectMax2 += sectBump;
if (draw_intersection <= 1 || !inStepRange) {
continue;
}
lastSect = tIndex;
sectCount += sectBump;
bumpStep = true;
}
if (recType == REC_TYPE_SORT) {
++sortMax;
if (!draw_sort || !inStepRange) {
continue;
}
lastSort = tIndex;
++sortCount;
bumpStep = true;
}
if (recType == REC_TYPE_TOP) {
++topMax;
if (!draw_top || !inStepRange) {
continue;
}
lastTop = tIndex;
++topCount;
bumpStep = true;
}
if (recType == REC_TYPE_MARK) {
++markMax;
if (!draw_mark || !inStepRange) {
continue;
}
lastMark = tIndex;
++markCount;
bumpStep = true;
}
if (bumpStep) {
lastIndex = tIndex;
logStart = test[tIndex + 1];
logRange = records.length / 2;
++curStep;
}
}
stepMax = (draw_add ? addMax : 0)
+ (draw_active ? activeMax : 0)
+ (draw_angle ? angleMax : 0)
+ (draw_coincidence ? coinMax : 0)
+ (draw_op ? opMax : 0)
+ (draw_sort ? sortMax : 0)
+ (draw_top ? topMax : 0)
+ (draw_mark ? markMax : 0)
+ (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
if (stepMax == 0) {
stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax;
}
drawnPts = [];
drawnLines = [];
drawnQuads = [];
drawnConics = [];
drawnCubics = [];
focusXmin = focusYmin = Infinity;
focusXmax = focusYmax = -Infinity;
var pathIndex = 0;
var opLetter = 'S';
for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
var recType = test[tIndex];
var records = test[tIndex + 2];
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
console.log("unknown in range frag type: " + fragType);
throw "stop execution";
}
var frags = records[recordIndex + 1];
focus_enabled = false;
switch (recType) {
case REC_TYPE_COMPUTED:
if (draw_computed == 0) {
continue;
}
ctx.lineWidth = 1;
ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
ctx.fillStyle = "blue";
var drawThis = false;
switch (fragType) {
case PATH_QUAD:
if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
&& (draw_computed & 7) == pathIndex)) {
drawQuad(frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5]);
drawThis = true;
}
break;
case PATH_CONIC:
if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
&& (draw_computed & 7) == pathIndex)) {
drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5], frags[6]);
drawThis = true;
}
break;
case PATH_CUBIC:
if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
&& (draw_computed & 7) == pathIndex)) {
drawCubic(frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5], frags[6], frags[7]);
drawThis = true;
}
++pathIndex;
break;
case COMPUTED_SET_1:
pathIndex = 0;
break;
case COMPUTED_SET_2:
pathIndex = 1;
break;
default:
console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
throw "stop execution";
}
if (!drawThis || collect_bounds) {
break;
}
drawCurveSpecials(test, frags, fragType);
break;
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
case REC_TYPE_ALIGNED:
if (draw_path < 4) {
continue;
}
case REC_TYPE_PATH:
case REC_TYPE_PATH2:
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
if (REC_TYPE_ALIGNED != recType && draw_path >= 4) {
continue;
}
if (!draw_path) {
continue;
}
var firstPath = tIndex < secondPath;
if ((draw_path & (firstPath ? 1 : 2)) == 0) {
continue;
}
ctx.lineWidth = 1;
ctx.strokeStyle = firstPath ? "black" : "red";
ctx.fillStyle = "blue";
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var frags2 = [];
switch (fragType) {
case PATH_LINE:
for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
break;
case PATH_QUAD:
for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
frags2[4], frags2[5]);
break;
case PATH_CONIC:
for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
frags2[4], frags2[5], frags2[6]);
break;
case PATH_CUBIC:
for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
frags2[4], frags2[5], frags2[6], frags2[7]);
break;
default:
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
console.log("unknown " + recType + " frag type: " + fragType);
throw "stop execution";
}
if (collect_bounds) {
break;
}
drawCurveSpecials(test, frags2, fragType);
break;
case REC_TYPE_OP:
switch (fragType) {
case OP_INTERSECT: opLetter = 'I'; break;
case OP_DIFFERENCE: opLetter = 'D'; break;
case OP_UNION: opLetter = 'U'; break;
case OP_XOR: opLetter = 'X'; break;
default:
console.log("unknown REC_TYPE_OP frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_ACTIVE:
if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
continue;
}
var x1 = frags[SPAN_X1];
var y1 = frags[SPAN_Y1];
var x2 = frags[SPAN_X2];
var y2 = frags[SPAN_Y2];
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var x3, y3, x3, y4, w;
ctx.lineWidth = 3;
ctx.strokeStyle = "rgba(0,0,255, 0.3)";
focus_enabled = true;
switch (fragType) {
case ACTIVE_LINE_SPAN:
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawLine(x1, y1, x2, y2);
if (draw_id) {
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawLineID(frags[0], x1, y1, x2, y2);
}
if (pt_labels) {
var curve = [x1, y1, x2, y2];
ctx.fillStyle = "blue";
drawPoints(curve, PATH_LINE, pt_labels == 2);
}
break;
case ACTIVE_QUAD_SPAN:
x3 = frags[SPAN_X3];
y3 = frags[SPAN_Y3];
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawQuad(x1, y1, x2, y2, x3, y3);
if (draw_id) {
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawQuadID(frags[0], x1, y1, x2, y2, x3, y3);
}
if (pt_labels) {
var curve = [x1, y1, x2, y2, x3, y3];
ctx.fillStyle = "blue";
drawPoints(curve, PATH_QUAD, pt_labels == 2);
}
break;
case ACTIVE_CONIC_SPAN:
x3 = frags[SPAN_X3];
y3 = frags[SPAN_Y3];
w = frags[SPAN_K_W];
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawConicWithQuads(x1, y1, x2, y2, x3, y3, w);
if (draw_id) {
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawConicID(frags[0], x1, y1, x2, y2, x3, y3, w);
}
if (pt_labels) {
var curve = [x1, y1, x2, y2, x3, y3, w];
ctx.fillStyle = "blue";
drawPoints(curve, PATH_CONIC, pt_labels == 2);
}
break;
case ACTIVE_CUBIC_SPAN:
x3 = frags[SPAN_X3];
y3 = frags[SPAN_Y3];
x4 = frags[SPAN_X4];
y4 = frags[SPAN_Y4];
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawCubic(x1, y1, x2, y2, x3, y3, x4, y4);
if (draw_id) {
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawCubicID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4);
}
if (pt_labels) {
var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
ctx.fillStyle = "blue";
drawPoints(curve, PATH_CUBIC, pt_labels == 2);
}
break;
default:
console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_ACTIVE_OP:
if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
continue;
}
focus_enabled = true;
ctx.lineWidth = 3;
var activeSpan = frags[7] == "1";
ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
drawCurve(curve);
if (draw_op > 1) {
drawArc(curve, false, frags[3], frags[4]);
drawArc(curve, true, frags[5], frags[6]);
}
break;
case REC_TYPE_ADD:
if (!draw_add) {
continue;
}
ctx.lineWidth = 3;
ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
: closeCount == 1 ? "rgba(0,127,0, 0.3)"
: closeCount == 2 ? "rgba(0,127,127, 0.3)"
: closeCount == 3 ? "rgba(127,127,0, 0.3)"
: "rgba(127,0,127, 0.3)";
focus_enabled = true;
switch (fragType) {
case ADD_MOVETO:
break;
case ADD_LINETO:
if (step_limit == 0 || tIndex >= lastAdd) {
drawLine(frags[0], frags[1], frags[2], frags[3]);
}
break;
case ADD_QUADTO:
if (step_limit == 0 || tIndex >= lastAdd) {
drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
}
break;
case ADD_CONICTO:
if (step_limit == 0 || tIndex >= lastAdd) {
drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5], frags[6]);
}
break;
case ADD_CUBICTO:
if (step_limit == 0 || tIndex >= lastAdd) {
drawCubic(frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5], frags[6], frags[7]);
}
break;
case ADD_CLOSE:
++closeCount;
break;
case ADD_FILL:
break;
default:
console.log("unknown REC_TYPE_ADD frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_ANGLE:
angleBetween = frags[18] == "T";
afterIndex = 0;
if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
continue;
}
focus_enabled = true;
ctx.lineWidth = 3;
ctx.strokeStyle = "rgba(127,45,127, 0.3)";
var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
drawCurve(leftCurve);
drawCurve(rightCurve);
ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
drawCurve(midCurve);
if (draw_angle > 1) {
drawVisibleOrder(leftCurve, 'L');
drawVisibleOrder(rightCurve, 'R');
}
if (draw_id) {
drawVisibleID(leftCurve, 0.5, frags[0]);
drawVisibleID(midCurve, 0.5, frags[6]);
drawVisibleID(rightCurve, 0.5, frags[12]);
}
break;
case REC_TYPE_AFTERPART:
if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
continue;
}
ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
: (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
: "rgba(0,0,255, 1.0)";
var curve;
var id;
switch (fragType) {
case PATH_LINE:
curve = [ frags[0], frags[1], frags[2], frags[3] ];
id = frags[4];
break;
case PATH_QUAD:
curve = [ frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5] ];
id = frags[6];
break;
case PATH_CONIC:
curve = [ frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5], frags[6] ];
id = frags[7];
break;
case PATH_CUBIC:
curve = [ frags[0], frags[1], frags[2], frags[3],
frags[4], frags[5], frags[6], frags[7] ];
id = frags[8];
break;
default:
console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
throw "stop execution";
}
drawCurve(curve);
if (draw_id) {
drawVisibleID(curve, 0.5, id);
}
++afterIndex;
break;
case REC_TYPE_COINCIDENCE:
if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) {
continue;
}
focus_enabled = true;
ctx.lineWidth = 3;
ctx.strokeStyle = "rgba(127,45,63, 0.3)";
var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
drawCurve(curve);
break;
case REC_TYPE_SECT:
if (!draw_intersection) {
continue;
}
if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
continue;
}
// draw_intersection == 1 : show all
// draw_intersection == 2 : step == 0 ? show all : show intersection line #step
// draw_intersection == 3 : step == 0 ? show all : show intersection #step
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(0,0,255, 0.3)";
ctx.fillStyle = "blue";
focus_enabled = true;
var f = [];
var c1s;
var c1l;
var c2s;
var c2l;
switch (fragType) {
case INTERSECT_LINE:
f.push(5, 6, 0, 7);
c1s = 1; c1l = 4; c2s = 8; c2l = 4;
break;
case INTERSECT_LINE_2:
f.push(5, 6, 0, 10);
f.push(8, 9, 7, 15);
c1s = 1; c1l = 4; c2s = 11; c2l = 4;
break;
case INTERSECT_LINE_NO:
c1s = 0; c1l = 4; c2s = 4; c2l = 4;
break;
case INTERSECT_QUAD_LINE:
f.push(7, 8, 0, 9);
c1s = 1; c1l = 6; c2s = 10; c2l = 4;
break;
case INTERSECT_QUAD_LINE_2:
f.push(7, 8, 0, 12);
f.push(10, 11, 9, 17);
c1s = 1; c1l = 6; c2s = 13; c2l = 4;
break;
case INTERSECT_QUAD_LINE_NO:
c1s = 0; c1l = 6; c2s = 6; c2l = 4;
break;
case INTERSECT_QUAD:
f.push(7, 8, 0, 9);
c1s = 1; c1l = 6; c2s = 10; c2l = 6;
break;
case INTERSECT_QUAD_2:
f.push(7, 8, 0, 12);
f.push(10, 11, 9, 19);
c1s = 1; c1l = 6; c2s = 13; c2l = 6;
break;
case INTERSECT_QUAD_NO:
c1s = 0; c1l = 6; c2s = 6; c2l = 6;
break;
case INTERSECT_CONIC_LINE:
f.push(8, 9, 0, 10);
c1s = 1; c1l = 7; c2s = 11; c2l = 4;
break;
case INTERSECT_CONIC_LINE_2:
f.push(8, 9, 0, 12);
f.push(11, 12, 10, 18);
c1s = 1; c1l = 7; c2s = 14; c2l = 4;
break;
case INTERSECT_CONIC_LINE_NO:
c1s = 0; c1l = 7; c2s = 7; c2l = 4;
break;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD:
f.push(8, 9, 0, 10);
c1s = 1; c1l = 7; c2s = 11; c2l = 6;
break;
case INTERSECT_CONIC_QUAD_2:
f.push(8, 9, 0, 12);
f.push(11, 12, 10, 18);
c1s = 1; c1l = 7; c2s = 14; c2l = 6;
break;
case INTERSECT_CONIC_QUAD_3:
f.push(8, 9, 0, 15);
f.push(11, 12, 10, 21);
f.push(14, 15, 13, 22);
c1s = 1; c1l = 7; c2s = 17; c2l = 6;
break;
case INTERSECT_CONIC_QUAD_4:
f.push(8, 9, 0, 18);
f.push(11, 12, 10, 24);
f.push(14, 15, 13, 25);
f.push(17, 18, 16, 26);
c1s = 1; c1l = 7; c2s = 20; c2l = 6;
break;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case INTERSECT_CONIC_QUAD_NO:
c1s = 0; c1l = 7; c2s = 7; c2l = 6;
break;
case INTERSECT_CONIC:
f.push(8, 9, 0, 10);
c1s = 1; c1l = 7; c2s = 11; c2l = 7;
break;
case INTERSECT_CONIC_2:
f.push(8, 9, 0, 13);
f.push(11, 12, 10, 21);
c1s = 1; c1l = 7; c2s = 14; c2l = 7;
break;
case INTERSECT_CONIC_NO:
c1s = 0; c1l = 7; c2s = 7; c2l = 7;
break;
case INTERSECT_SELF_CUBIC:
f.push(9, 10, 0, 11);
c1s = 1; c1l = 8; c2s = 0; c2l = 0;
break;
case INTERSECT_SELF_CUBIC_NO:
c1s = 0; c1l = 8; c2s = 0; c2l = 0;
break;
case INTERSECT_CUBIC_LINE:
f.push(9, 10, 0, 11);
c1s = 1; c1l = 8; c2s = 12; c2l = 4;
break;
case INTERSECT_CUBIC_LINE_2:
f.push(9, 10, 0, 14);
f.push(12, 13, 11, 19);
c1s = 1; c1l = 8; c2s = 15; c2l = 4;
break;
case INTERSECT_CUBIC_LINE_3:
f.push(9, 10, 0, 17);
f.push(12, 13, 11, 22);
f.push(15, 16, 14, 23);
c1s = 1; c1l = 8; c2s = 18; c2l = 4;
break;
case INTERSECT_CUBIC_QUAD_NO:
c1s = 0; c1l = 8; c2s = 8; c2l = 6;
break;
case INTERSECT_CUBIC_QUAD:
f.push(9, 10, 0, 11);
c1s = 1; c1l = 8; c2s = 12; c2l = 6;
break;
case INTERSECT_CUBIC_QUAD_2:
f.push(9, 10, 0, 14);
f.push(12, 13, 11, 21);
c1s = 1; c1l = 8; c2s = 15; c2l = 6;
break;
case INTERSECT_CUBIC_QUAD_3:
f.push(9, 10, 0, 17);
f.push(12, 13, 11, 24);
f.push(15, 16, 14, 25);
c1s = 1; c1l = 8; c2s = 18; c2l = 6;
break;
case INTERSECT_CUBIC_QUAD_4:
f.push(9, 10, 0, 20);
f.push(12, 13, 11, 27);
f.push(15, 16, 14, 28);
f.push(18, 19, 17, 29);
c1s = 1; c1l = 8; c2s = 21; c2l = 6;
break;
case INTERSECT_CUBIC_LINE_NO:
c1s = 0; c1l = 8; c2s = 8; c2l = 4;
break;
case INTERSECT_CUBIC:
f.push(9, 10, 0, 11);
c1s = 1; c1l = 8; c2s = 12; c2l = 8;
break;
case INTERSECT_CUBIC_2:
f.push(9, 10, 0, 14);
f.push(12, 13, 11, 23);
c1s = 1; c1l = 8; c2s = 15; c2l = 8;
break;
case INTERSECT_CUBIC_3:
f.push(9, 10, 0, 17);
f.push(12, 13, 11, 26);
f.push(15, 16, 14, 27);
c1s = 1; c1l = 8; c2s = 18; c2l = 8;
break;
case INTERSECT_CUBIC_4:
f.push(9, 10, 0, 20);
f.push(12, 13, 11, 29);
f.push(15, 16, 14, 30);
f.push(18, 19, 17, 31);
c1s = 1; c1l = 8; c2s = 21; c2l = 8;
break;
case INTERSECT_CUBIC_NO:
c1s = 0; c1l = 8; c2s = 8; c2l = 8;
break;
default:
console.log("unknown REC_TYPE_SECT frag type: " + fragType);
throw "stop execution";
}
if (draw_intersection != 1) {
var id = -1;
var curve;
switch (c1l) {
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case 4:
drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
if (draw_id) {
curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
id = idByCurve(test, curve, PATH_LINE);
}
break;
case 6:
drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
frags[c1s + 4], frags[c1s + 5]);
if (draw_id) {
curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
frags[c1s + 4], frags[c1s + 5]];
id = idByCurve(test, curve, PATH_QUAD);
}
break;
case 7:
drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
if (draw_id) {
curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
id = idByCurve(test, curve, PATH_CONIC);
}
break;
case 8:
drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
if (draw_id) {
curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
id = idByCurve(test, curve, PATH_CUBIC);
}
break;
}
if (id >= 0) {
drawVisibleID(curve, 0.5, id);
}
id = -1;
switch (c2l) {
case 0:
break;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
case 4:
drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
if (draw_id) {
curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
id = idByCurve(test, curve, PATH_LINE);
}
break;
case 6:
drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
frags[c2s + 4], frags[c2s + 5]);
if (draw_id) {
curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
frags[c2s + 4], frags[c2s + 5]];
id = idByCurve(test, curve, PATH_QUAD);
}
break;
case 7:
drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
if (draw_id) {
curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
id = idByCurve(test, curve, PATH_CONIC);
}
break;
case 8:
drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
if (draw_id) {
curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
id = idByCurve(test, curve, PATH_CUBIC);
}
break;
}
if (id >= 0) {
drawVisibleID(curve, 0.5, id);
}
}
if (collect_bounds) {
break;
}
if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
for (var idx = 0; idx < f.length; idx += 4) {
drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
}
}
if (!draw_intersectT) {
break;
}
ctx.fillStyle = "red";
if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
for (var idx = 0; idx < f.length; idx += 4) {
drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
}
}
break;
case REC_TYPE_SORT:
if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
continue;
}
ctx.lineWidth = 3;
ctx.strokeStyle = "rgba(127,127,0, 0.5)";
focus_enabled = true;
switch (fragType) {
case SORT_UNARY:
case SORT_BINARY:
var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
drawCurve(curve);
break;
default:
console.log("unknown REC_TYPE_SORT frag type: " + fragType);
throw "stop execution";
}
break;
case REC_TYPE_TOP:
if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
continue;
}
ctx.lineWidth = 3;
ctx.strokeStyle = "rgba(127,127,0, 0.5)";
focus_enabled = true;
{
var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
drawCurve(curve);
var type = PATH_LINE + (curve.length / 2 - 2);
var mid = pointAtT(curve, type, 0.5);
var d = dxy_at_t(curve, type, 0.5);
drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
}
break;
case REC_TYPE_MARK:
if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
continue;
}
ctx.lineWidth = 3;
ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
"rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
focus_enabled = true;
switch (fragType) {
case MARK_LINE:
case MARK_DONE_LINE:
case MARK_UNSORTABLE_LINE:
case MARK_SIMPLE_LINE:
case MARK_SIMPLE_DONE_LINE:
case MARK_DONE_UNARY_LINE:
drawLinePartial(frags[1], frags[2], frags[3], frags[4],
frags[5], frags[9]);
if (draw_id) {
drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
frags[5], frags[9]);
}
break;
case MARK_QUAD:
case MARK_DONE_QUAD:
case MARK_UNSORTABLE_QUAD:
case MARK_SIMPLE_QUAD:
case MARK_SIMPLE_DONE_QUAD:
case MARK_DONE_UNARY_QUAD:
drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], frags[11]);
if (draw_id) {
drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], frags[11]);
}
break;
case MARK_CUBIC:
case MARK_DONE_CUBIC:
case MARK_UNSORTABLE_CUBIC:
case MARK_SIMPLE_CUBIC:
case MARK_SIMPLE_DONE_CUBIC:
case MARK_DONE_UNARY_CUBIC:
drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
if (draw_id) {
drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
}
break;
case MARK_ANGLE_LAST:
// FIXME: ignored for now
break;
default:
console.log("unknown REC_TYPE_MARK frag type: " + fragType);
throw "stop execution";
}
break;
default:
continue;
}
}
switch (recType) {
case REC_TYPE_SORT:
if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
break;
}
var angles = []; // use tangent lines to describe arcs
var windFrom = [];
var windTo = [];
var opp = [];
var minXY = Number.MAX_VALUE;
var partial;
focus_enabled = true;
var someUnsortable = false;
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
var frags = records[recordIndex + 1];
var unsortable = (fragType == SORT_UNARY && frags[14]) ||
(fragType == SORT_BINARY && frags[16]);
someUnsortable |= unsortable;
switch (fragType) {
case SORT_UNARY:
case SORT_BINARY:
partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
break;
default:
console.log("unknown REC_TYPE_SORT frag type: " + fragType);
throw "stop execution";
}
var dx = boundsWidth(partial);
var dy = boundsHeight(partial);
minXY = Math.min(minXY, dx * dx + dy * dy);
if (collect_bounds) {
continue;
}
angles.push(tangent(partial));
var from = frags[12];
var to = frags[12];
var sgn = frags[10];
if (sgn < 0) {
from -= frags[11];
} else if (sgn > 0) {
to -= frags[11];
}
windFrom.push(from + (unsortable ? "!" : ""));
windTo.push(to + (unsortable ? "!" : ""));
opp.push(fragType == SORT_BINARY);
if (draw_sort == 1) {
drawVisibleOrder(partial, frags[12]);
} else {
drawVisibleOrder(partial, (recordIndex / 2) + 1);
}
}
var radius = Math.sqrt(minXY) / 2 * scale;
radius = Math.min(50, radius);
var scaledRadius = radius / scale;
var centerX = partial[0];
var centerY = partial[1];
if (collect_bounds) {
if (focus_enabled) {
focusXmin = Math.min(focusXmin, centerX - scaledRadius);
focusYmin = Math.min(focusYmin, centerY - scaledRadius);
focusXmax = Math.max(focusXmax, centerX + scaledRadius);
focusYmax = Math.max(focusYmax, centerY + scaledRadius);
}
break;
}
break;
default:
break;
}
}
if (collect_bounds) {
return;
}
if (draw_log && logStart >= 0) {
ctx.font = "normal 10px Arial";
ctx.textAlign = "left";
ctx.beginPath();
var top = screenHeight - 20 - (logRange + 2) * 10;
ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
ctx.fillStyle = "white";
ctx.fill();
ctx.fillStyle = "rgba(0,0,0, 0.5)";
if (logStart > 0) {
ctx.fillText(lines[logStart - 1], 50, top + 8);
}
ctx.fillStyle = "black";
for (var idx = 0; idx < logRange; ++idx) {
ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
}
ctx.fillStyle = "rgba(0,0,0, 0.5)";
if (logStart + logRange < lines.length) {
ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
}
}
if (draw_legend) {
var pos = 0;
var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark;
// drawBox(pos++, "yellow", "black", opLetter, true, '');
drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey);
drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
drawBox(pos++, "black", "white",
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
(new Array('P', 'P1', 'P2', 'P', 'p', 'p1', 'p2'))[draw_path], draw_path != 0, pathKey);
drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
(new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
draw_computed != 0, computedKey);
drawBox(pos++, "green", "black", step_limit, drawSomething, '');
drawBox(pos++, "green", "black", stepMax, drawSomething, '');
drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
if (curve_t) {
drawCurveTControl();
}
ctx.font = "normal 20px Arial";
ctx.fillStyle = "rgba(0,0,0, 0.3)";
ctx.textAlign = "right";
ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
}
if (draw_hints) {
ctx.font = "normal 10px Arial";
ctx.fillStyle = "rgba(0,0,0, 0.5)";
ctx.textAlign = "right";
var y = 4;
ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
}
}
function drawBox(y, backC, foreC, str, enable, label) {
ctx.beginPath();
ctx.fillStyle = backC;
ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
ctx.fill();
ctx.font = "normal 16px Arial";
ctx.fillStyle = foreC;
ctx.textAlign = "center";
ctx.fillText(str, screenWidth - 20, y * 50 + 32);
if (!enable) {
ctx.fillStyle = "rgba(255,255,255, 0.5)";
ctx.fill();
}
if (label != '') {
ctx.font = "normal 9px Arial";
ctx.fillStyle = "black";
ctx.fillText(label, screenWidth - 47, y * 50 + 40);
}
}
function drawCurveTControl() {
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(0,0,0, 0.3)";
ctx.beginPath();
ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
ctx.stroke();
var ty = 40 + curveT * (screenHeight - 80);
ctx.beginPath();
ctx.moveTo(screenWidth - 80, ty);
ctx.lineTo(screenWidth - 85, ty - 5);
ctx.lineTo(screenWidth - 85, ty + 5);
ctx.lineTo(screenWidth - 80, ty);
ctx.fillStyle = "rgba(0,0,0, 0.6)";
ctx.fill();
var num = curveT.toFixed(decimal_places);
ctx.font = "normal 10px Arial";
ctx.textAlign = "left";
ctx.fillText(num, screenWidth - 78, ty);
}
function ptInTControl() {
var e = window.event;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var tgt = e.target || e.srcElement;
var left = tgt.offsetLeft;
var top = tgt.offsetTop;
var x = (e.clientX - left);
var y = (e.clientY - top);
if (x < screenWidth - 80 || x > screenWidth - 50) {
return false;
}
if (y < 40 || y > screenHeight - 80) {
return false;
}
curveT = (y - 40) / (screenHeight - 120);
if (curveT < 0 || curveT > 1) {
throw "stop execution";
}
return true;
}
function drawTop() {
if (tests[testIndex] == null) {
var str = testDivs[testIndex].textContent;
parse_all(str);
var title = testDivs[testIndex].id.toString();
testTitles[testIndex] = title;
}
init(tests[testIndex]);
redraw();
}
function redraw() {
if (focus_on_selection) {
collect_bounds = true;
draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
collect_bounds = false;
if (focusXmin < focusXmax && focusYmin < focusYmax) {
setScale(focusXmin, focusXmax, focusYmin, focusYmax);
}
}
ctx.beginPath();
ctx.fillStyle = "white";
ctx.rect(0, 0, screenWidth, screenHeight);
ctx.fill();
draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
}
function dumpCurvePartial(test, id, t0, t1) {
var curve = curveByID(test, id);
var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
console.log("id=" + id + " " + name + "=" + curveToString(curve)
+ " t0=" + t0 + " t1=" + t1
+ " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
}
function dumpAngleTest(test, id, t0, t1) {
var curve = curveByID(test, id);
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
console.log(" { {" + curveToString(curve) + "}, "
+ curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
}
function dumpLogToConsole() {
if (logStart < 0) {
return;
}
var test = tests[testIndex];
var recType = REC_TYPE_UNKNOWN;
var records;
for (var index = 0; index < test.length; index += 3) {
var lastLineNo = test[index + 1];
if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
recType = test[index];
records = test[index + 2];
break;
}
}
if (recType == REC_TYPE_UNKNOWN) {
return;
}
var lines = testLines[testIndex];
for (var idx = 0; idx < logRange; ++idx) {
var line = lines[logStart + idx];
console.log(line);
for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
var fragType = records[recordIndex];
var frags = records[recordIndex + 1];
if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
dumpCurvePartial(test, frags[0], frags[4], frags[5]);
dumpCurvePartial(test, frags[6], frags[10], frags[11]);
dumpCurvePartial(test, frags[12], frags[16], frags[17]);
console.log("\nstatic IntersectData intersectDataSet[] = { //");
dumpAngleTest(test, frags[0], frags[4], frags[5]);
dumpAngleTest(test, frags[6], frags[10], frags[11]);
dumpAngleTest(test, frags[12], frags[16], frags[17]);
console.log("}; //");
}
}
}
}
var activeKey = 'a';
var pathKey = 'b';
var pathBackKey = 'B';
var centerKey = 'c';
var coincidenceKey = 'C';
var addKey = 'd';
var deriviativesKey = 'f';
var angleKey = 'g';
var angleBackKey = 'G';
var intersectionKey = 'i';
var intersectionBackKey = 'I';
var sequenceKey = 'j';
var midpointKey = 'k';
var logKey = 'l';
var logToConsoleKey = 'L';
var markKey = 'm';
var sortKey = 'o';
var opKey = 'p';
var opBackKey = 'P';
var computedKey = 'q';
var computedBackKey = 'Q';
var directionKey = 'r';
var stepKey = 's';
var stepBackKey = 'S';
var intersectTKey = 't';
var topKey = 'T';
var curveTKey = 'u';
var controlLinesBackKey = 'V';
var controlLinesKey = 'v';
var ptsKey = 'x';
var xyKey = 'y';
var logCurvesKey = 'z';
var focusKey = '`';
var idKey = '.';
var retinaKey = '\\';
function doKeyPress(evt) {
var char = String.fromCharCode(evt.charCode);
var focusWasOn = false;
switch (char) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
decimal_places = char - '0';
redraw();
break;
case activeKey:
draw_active ^= true;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case addKey:
draw_add ^= true;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case angleKey:
draw_angle = (draw_angle + 1) % 4;
redraw();
break;
case angleBackKey:
draw_angle = (draw_angle + 2) % 3;
redraw();
break;
case centerKey:
setScale(xmin, xmax, ymin, ymax);
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case coincidenceKey:
draw_coincidence ^= true;
redraw();
break;
case controlLinesBackKey:
control_lines = (control_lines + 3) % 4;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case controlLinesKey:
control_lines = (control_lines + 1) % 4;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case computedBackKey:
draw_computed = (draw_computed + 5) % 6;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case computedKey:
draw_computed = (draw_computed + 1) % 6;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case curveTKey:
curve_t ^= true;
if (curve_t) {
draw_legend = true;
}
redraw();
break;
case deriviativesKey:
draw_deriviatives = (draw_deriviatives + 1) % 3;
redraw();
break;
case directionKey:
draw_direction ^= true;
redraw();
break;
case focusKey:
focus_on_selection ^= true;
setScale(xmin, xmax, ymin, ymax);
redraw();
break;
case idKey:
draw_id ^= true;
redraw();
break;
case intersectionBackKey:
draw_intersection = (draw_intersection + 3) % 4;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case intersectionKey:
draw_intersection = (draw_intersection + 1) % 4;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case intersectTKey:
draw_intersectT ^= true;
redraw();
break;
case logCurvesKey:
logCurves(tests[testIndex]);
break;
case logKey:
draw_log ^= true;
redraw();
break;
case logToConsoleKey:
if (draw_log) {
dumpLogToConsole();
}
break;
case markKey:
draw_mark ^= true;
redraw();
break;
case midpointKey:
draw_midpoint ^= true;
redraw();
break;
case opKey:
draw_op = (draw_op + 1) % 3;
redraw();
break;
case opBackKey:
draw_op = (draw_op + 2) % 3;
redraw();
break;
case pathKey:
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
draw_path = (draw_path + 1) % (4 + (hasAlignedPath ? 3 : 0));
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case pathBackKey:
Enabling clip stack flattening exercises path ops. Iterating through the 903K skps that represent the imagable 1M top web pages triggers a number of bugs, some of which are addressed here. Some web pages trigger intersecting cubic representations of arc with their conic counterparts. This exposed a flaw in coincident detection that caused an infinite loop. The loop alternatively extended the coincident section and, determining the that the bounds of the curve pairs did not overlap, deleted the extension. Track the number of times the coincident detection is called, and if it exceeds an empirically found limit, assume that the curves are coincident and force it to be so. The loop count limit can be determined by enabling DEBUG_T_SECT_LOOP_COUNT and running all tests. The largest count is reported on completion. Another class of bugs was caused by concident detection duplicating nearly identical points that had been merged earlier. To track these bugs, the 'handle coincidence' code was duplicated as a const debug variety that reported if one of a dozen or so irregularities are present; then it is easier to see when a block of code that fixes one irregularity regresses another. Creating the debug const code version exposed some non-debug code that could be const, and some that was experimental and could be removed. Set DEBUG_COINCIDENCE to track coincidence health and handling. For running on Chrome, DEBUG_VERIFY checks the result of pathops against the same operation using SkRegion to verify that the results are nearly the same. When visualizing the pathops work using tools/pathops_visualizer.htm, set DEBUG_DUMP_ALIGNMENT to see the curves after they've been aligned for coincidence. Other bugs fixed include detecting when a section of a pair of curves have devolved into lines and are coincident. TBR=reed@google.com Review URL: https://codereview.chromium.org/1394503003
2015-10-16 16:03:38 +00:00
draw_path = (draw_path + 3 + (hasAlignedPath ? 3 : 0)) % (4 + (hasAlignedPath ? 3 : 0));
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
redraw();
break;
case ptsKey:
pt_labels = (pt_labels + 1) % 3;
redraw();
break;
case retinaKey:
retina_scale ^= true;
drawTop();
break;
case sequenceKey:
draw_sequence ^= true;
redraw();
break;
case sortKey:
draw_sort = (draw_sort + 1) % 3;
drawTop();
break;
case stepKey:
step_limit++;
if (step_limit > stepMax) {
step_limit = stepMax;
}
redraw();
break;
case stepBackKey:
step_limit--;
if (step_limit < 0) {
step_limit = 0;
}
redraw();
break;
case topKey:
draw_top ^= true;
redraw();
break;
case xyKey:
debug_xy = (debug_xy + 1) % 3;
redraw();
break;
case '-':
focusWasOn = focus_on_selection;
if (focusWasOn) {
focus_on_selection = false;
scale /= 1.2;
} else {
scale /= 2;
calcLeftTop();
}
redraw();
focus_on_selection = focusWasOn;
break;
case '=':
case '+':
focusWasOn = focus_on_selection;
if (focusWasOn) {
focus_on_selection = false;
scale *= 1.2;
} else {
scale *= 2;
calcLeftTop();
}
redraw();
focus_on_selection = focusWasOn;
break;
case '?':
draw_hints ^= true;
if (draw_hints && !draw_legend) {
draw_legend = true;
}
redraw();
break;
case '/':
draw_legend ^= true;
redraw();
break;
}
}
function doKeyDown(evt) {
var char = evt.keyCode;
var preventDefault = false;
switch (char) {
case 37: // left arrow
if (evt.shiftKey) {
testIndex -= 9;
}
if (--testIndex < 0)
testIndex = tests.length - 1;
drawTop();
preventDefault = true;
break;
case 39: // right arrow
if (evt.shiftKey) {
testIndex += 9;
}
if (++testIndex >= tests.length)
testIndex = 0;
drawTop();
preventDefault = true;
break;
}
if (preventDefault) {
evt.preventDefault();
return false;
}
return true;
}
(function() {
var hidden = "hidden";
// Standards:
if (hidden in document)
document.addEventListener("visibilitychange", onchange);
else if ((hidden = "mozHidden") in document)
document.addEventListener("mozvisibilitychange", onchange);
else if ((hidden = "webkitHidden") in document)
document.addEventListener("webkitvisibilitychange", onchange);
else if ((hidden = "msHidden") in document)
document.addEventListener("msvisibilitychange", onchange);
// IE 9 and lower:
else if ('onfocusin' in document)
document.onfocusin = document.onfocusout = onchange;
// All others:
else
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
window.onpageshow = window.onpagehide
= window.onfocus = window.onblur = onchange;
function onchange (evt) {
var v = 'visible', h = 'hidden',
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
evtMap = {
focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
};
evt = evt || window.event;
if (evt.type in evtMap)
document.body.className = evtMap[evt.type];
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
else
document.body.className = this[hidden] ? "hidden" : "visible";
}
})();
function calcXY() {
var e = window.event;
pathops coincidence and security rewrite Most changes stem from working on an examples bracketed by #if DEBUG_UNDER_DEVELOPMENT // tiger These exposed many problems with coincident curves, as well as errors throughout the code. Fixing these errors also fixed a number of fuzzer-inspired bug reports. * Line/Curve Intersections Check to see if the end of the line nearly intersects the curve. This was a FIXME in the old code. * Performance Use a central chunk allocator. Plumb the allocator into the global variable state so that it can be shared. (Note that 'SkGlobalState' is allocated on the stack and is visible to children functions but not other threads.) * Refactor Let SkOpAngle grow up from a structure to a class. Let SkCoincidentSpans grow up from a structure to a class. Rename enum Alias to AliasMatch. * Coincidence Rewrite Add more debugging to coincidence detection. Parallel debugging routines have read-only logic to report the current coincidence state so that steps through the logic can expose whether things got better or worse. More functions can error-out and cause the pathops engine to non-destructively exit. * Accuracy Remove code that adjusted point locations. Instead, offset the curve part so that sorted curves all use the same origin. Reduce the size (and influence) of magic numbers. * Testing The debug suite with verify and the full release suite ./out/Debug/pathops_unittest -v -V ./out/Release/pathops_unittest -v -V -x expose one error. That error is captured as cubics_d3. This error exists in the checked in code as well. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003 Review-Url: https://codereview.chromium.org/2128633003
2016-07-18 17:01:36 +00:00
var tgt = e.target || e.srcElement;
var left = tgt.offsetLeft;
var top = tgt.offsetTop;
mouseX = (e.clientX - left) / scale + srcLeft;
mouseY = (e.clientY - top) / scale + srcTop;
}
function calcLeftTop() {
srcLeft = mouseX - screenWidth / 2 / scale;
srcTop = mouseY - screenHeight / 2 / scale;
}
var disableClick = false;
function handleMouseClick() {
if (disableClick) {
return;
}
if (!curve_t || !ptInTControl()) {
calcXY();
calcLeftTop();
}
redraw();
// if (!curve_t || !ptInTControl()) {
// mouseX = screenWidth / 2 / scale + srcLeft;
// mouseY = screenHeight / 2 / scale + srcTop;
// }
}
function handleMouseOver() {
calcXY();
if (debug_xy != 2) {
return;
}
var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
ctx.beginPath();
ctx.rect(300,100,num.length * 6,10);
ctx.fillStyle="white";
ctx.fill();
ctx.font = "normal 10px Arial";
ctx.fillStyle="black";
ctx.textAlign = "left";
ctx.fillText(num, 300, 108);
}
function start() {
for (var i = 0; i < testDivs.length; ++i) {
tests[i] = null;
}
testIndex = 0;
drawTop();
window.addEventListener('keypress', doKeyPress, true);
window.addEventListener('keydown', doKeyDown, true);
window.onresize = function() {
drawTop();
}
/*
window.onpagehide = function() {
disableClick = true;
}
*/
window.onpageshow = function () {
disableClick = false;
}
}
</script>
</head>
<body onLoad="start();">
<canvas id="canvas" width="750" height="500"
onmousemove="handleMouseOver()"
onclick="handleMouseClick()"
></canvas >
</body>
</html>