blob: f8b49d6cdcb1e7f201dfe4279893b408f1aa2c97 [file] [log] [blame]
caryclarkdac1d172014-06-17 05:15:38 -07001<html>
2<head>
3<div height="0" hidden="true">
caryclarkdac1d172014-06-17 05:15:38 -07004
caryclark1049f122015-04-20 08:31:59 -07005<div id="cubicOp132">
6seg=1 {{{5, 6}, {3.38059044f, 4.38059044f}, {3.07242441f, 1.44993687f}, {3.01378202f, 1.45492136f}}}
7seg=2 {{{3.01378202f, 1.45492136f}, {3, 1.45609283f}, {3, 1.61940968f}, {3, 2}}}
8seg=3 {{{3, 2}, {5, 6}}}
9op diff
10seg=4 {{{0, 3}, {0.763932049f, 3}, {1.81966019f, 3.29179597f}, {2.72135973f, 3.54101968f}}}
11seg=5 {{{2.72135973f, 3.54101968f}, {4.18033981f, 3.9442718f}, {5.23606777f, 4.23606777f}, {4, 3}}}
12seg=6 {{{4, 3}, {0, 3}}}
13debugShowCubicIntersection wtTs[0]=1 {{{5,6}, {3.38059044,4.38059044}, {3.07242441,1.44993687}, {3.01378202,1.45492136}}} {{3.01378202,1.45492136}} wnTs[0]=0 {{{3.01378202,1.45492136}, {3,1.45609283}, {3,1.61940968}, {3,2}}}
14debugShowCubicLineIntersection wtTs[0]=0 {{{5,6}, {3.38059044,4.38059044}, {3.07242441,1.44993687}, {3.01378202,1.45492136}}} {{5,6}} wtTs[1]=0.617509 {{3.25,2.5}} wnTs[0]=1 {{{3,2}, {5,6}}} wnTs[1]=0.124999978
15SkOpSegment::addT insert t=0.617509 segID=1 spanID=13
16SkOpSegment::addT insert t=0.124999978 segID=3 spanID=14
17debugShowCubicLineIntersection wtTs[0]=1 {{{3.01378202,1.45492136}, {3,1.45609283}, {3,1.61940968}, {3,2}}} {{3,2}} wnTs[0]=0 {{{3,2}, {5,6}}}
18debugShowCubicIntersection wtTs[0]=0.385353706 {{{5,6}, {3.38059044,4.38059044}, {3.07242441,1.44993687}, {3.01378202,1.45492136}}} {{3.6512568,3.78673816}} wnTs[0]=0.232896 {{{2.72135973,3.54101968}, {4.18033981,3.9442718}, {5.23606777,4.23606777}, {4,3}}}
19SkOpSegment::addT insert t=0.385353706 segID=1 spanID=15
20SkOpSegment::addT insert t=0.23289595 segID=5 spanID=16
21debugShowCubicLineIntersection wtTs[0]=0.521306291 {{{5,6}, {3.38059044,4.38059044}, {3.07242441,1.44993687}, {3.01378202,1.45492136}}} {{3.38599229,3}} wnTs[0]=0.153502 {{{4,3}, {0,3}}}
22SkOpSegment::addT insert t=0.521306291 segID=1 spanID=17
23SkOpSegment::addT insert t=0.153501943 segID=6 spanID=18
24debugShowCubicLineIntersection wtTs[0]=0.31546775 {{{2.72135973,3.54101968}, {4.18033981,3.9442718}, {5.23606777,4.23606777}, {4,3}}} {{3.92245698,3.84491396}} wnTs[0]=0.461228 {{{3,2}, {5,6}}}
25SkOpSegment::addT insert t=0.461228479 segID=3 spanID=19
26SkOpSegment::addT insert t=0.31546775 segID=5 spanID=20
27debugShowLineIntersection wtTs[0]=0.25 {{{3,2}, {5,6}}} {{3.5,3}} wnTs[0]=0.125 {{{4,3}, {0,3}}}
28SkOpSegment::addT insert t=0.25 segID=3 spanID=21
29SkOpSegment::addT insert t=0.125 segID=6 spanID=22
30debugShowCubicIntersection wtTs[0]=1 {{{0,3}, {0.763932049,3}, {1.81966019,3.29179597}, {2.72135973,3.54101968}}} {{2.72135973,3.54101968}} wnTs[0]=0 {{{2.72135973,3.54101968}, {4.18033981,3.9442718}, {5.23606777,4.23606777}, {4,3}}}
31debugShowCubicLineIntersection wtTs[0]=0 {{{0,3}, {0.763932049,3}, {1.81966019,3.29179597}, {2.72135973,3.54101968}}} {{0,3}} wnTs[0]=1 {{{4,3}, {0,3}}}
32debugShowCubicLineIntersection wtTs[0]=1 {{{2.72135973,3.54101968}, {4.18033981,3.9442718}, {5.23606777,4.23606777}, {4,3}}} {{4,3}} wnTs[0]=0 {{{4,3}, {0,3}}}
33SkOpSegment::sortAngles [1] tStart=0.385353706 [15]
34SkOpAngle::after [1/1] 25/25 tStart=0.385353706 tEnd=0 < [5/13] 13/13 tStart=0.23289595 tEnd=0 < [1/2] 9/9 tStart=0.385353706 tEnd=0.521306291 F 4
35SkOpAngle::afterPart {{{3.6512568,3.78673816}, {3.94662547,4.55719268}, {4.37595452,5.37595452}, {5,6}}} id=1
36SkOpAngle::afterPart {{{3.6512568,3.78673816}, {3.37906829,3.72280588}, {3.06115028,3.63493546}, {2.72135973,3.54101968}}} id=5
37SkOpAngle::afterPart {{{3.6512568,3.78673816}, {3.54705089,3.5149222}, {3.45951868,3.24911888}, {3.38599229,3}}} id=1
38SkOpAngle::after [1/1] 25/25 tStart=0.385353706 tEnd=0 < [5/14] 29/29 tStart=0.23289595 tEnd=0.31546775 < [1/2] 9/9 tStart=0.385353706 tEnd=0.521306291 T 4
39SkOpAngle::afterPart {{{3.6512568,3.78673816}, {3.94662547,4.55719268}, {4.37595452,5.37595452}, {5,6}}} id=1
40SkOpAngle::afterPart {{{3.6512568,3.78673816}, {3.74775953,3.80940495}, {3.83851397,3.82906267}, {3.92245698,3.84491396}}} id=5
41SkOpAngle::afterPart {{{3.6512568,3.78673816}, {3.54705089,3.5149222}, {3.45951868,3.24911888}, {3.38599229,3}}} id=1
42SkOpSegment::sortAngles [1] tStart=0.521306291 [17]
43SkOpAngle::after [1/3] 25/25 tStart=0.521306291 tEnd=0.385353706 < [6/19] 31/31 tStart=0.153501943 tEnd=0.125 < [1/4] 9/9 tStart=0.521306291 tEnd=0.617509 T 4
44SkOpAngle::afterPart {{{3.38599229,3}, {3.45951868,3.24911888}, {3.54705089,3.5149222}, {3.6512568,3.78673816}}} id=1
45SkOpAngle::afterPart {{{3.38599229,3}, {3.5,3}}} id=6
46SkOpAngle::afterPart {{{3.38599229,3}, {3.33396357,2.82371861}, {3.2889479,2.65579159}, {3.25,2.5}}} id=1
47SkOpAngle::after [1/3] 25/25 tStart=0.521306291 tEnd=0.385353706 < [6/20] 15/15 tStart=0.153501943 tEnd=1 < [6/19] 31/31 tStart=0.153501943 tEnd=0.125 F 4
48SkOpAngle::afterPart {{{3.38599229,3}, {3.45951868,3.24911888}, {3.54705089,3.5149222}, {3.6512568,3.78673816}}} id=1
49SkOpAngle::afterPart {{{3.38599229,3}, {0,3}}} id=6
50SkOpAngle::afterPart {{{3.38599229,3}, {3.5,3}}} id=6
51SkOpAngle::after [6/19] 31/31 tStart=0.153501943 tEnd=0.125 < [6/20] 15/15 tStart=0.153501943 tEnd=1 < [1/4] 9/9 tStart=0.521306291 tEnd=0.617509 F 4
52SkOpAngle::afterPart {{{3.38599229,3}, {3.5,3}}} id=6
53SkOpAngle::afterPart {{{3.38599229,3}, {0,3}}} id=6
54SkOpAngle::afterPart {{{3.38599229,3}, {3.33396357,2.82371861}, {3.2889479,2.65579159}, {3.25,2.5}}} id=1
55SkOpAngle::after [1/4] 9/9 tStart=0.521306291 tEnd=0.617509 < [6/20] 15/15 tStart=0.153501943 tEnd=1 < [1/3] 25/25 tStart=0.521306291 tEnd=0.385353706 T 4
56SkOpAngle::afterPart {{{3.38599229,3}, {3.33396357,2.82371861}, {3.2889479,2.65579159}, {3.25,2.5}}} id=1
57SkOpAngle::afterPart {{{3.38599229,3}, {0,3}}} id=6
58SkOpAngle::afterPart {{{3.38599229,3}, {3.45951868,3.24911888}, {3.54705089,3.5149222}, {3.6512568,3.78673816}}} id=1
59SkOpSegment::sortAngles [1] tStart=0.617509 [13]
60SkOpAngle::after [1/5] 25/25 tStart=0.617509 tEnd=0.521306291 < [3/7] 9/9 tStart=0.124999978 tEnd=0 < [1/6] 9/9 tStart=0.617509 tEnd=1 F 11
61SkOpAngle::afterPart {{{3.25,2.5}, {3.2889479,2.65579159}, {3.33396357,2.82371861}, {3.38599229,3}}} id=1
62SkOpAngle::afterPart {{{3.25,2.5}, {3,2}}} id=3
63SkOpAngle::afterPart {{{3.25,2.5}, {3.09514759,1.88059039}, {3.03621221,1.45301484}, {3.01378202,1.45492136}}} id=1
64SkOpAngle::after [1/5] 25/25 tStart=0.617509 tEnd=0.521306291 < [3/8] 25/25 tStart=0.124999978 tEnd=0.25 < [1/6] 9/9 tStart=0.617509 tEnd=1 T 12
65SkOpAngle::afterPart {{{3.25,2.5}, {3.2889479,2.65579159}, {3.33396357,2.82371861}, {3.38599229,3}}} id=1
66SkOpAngle::afterPart {{{3.25,2.5}, {3.5,3}}} id=3
67SkOpAngle::afterPart {{{3.25,2.5}, {3.09514759,1.88059039}, {3.03621221,1.45301484}, {3.01378202,1.45492136}}} id=1
68SkOpSegment::sortAngles [3] tStart=0.124999978 [14]
69SkOpSegment::sortAngles [3] tStart=0.25 [21]
70SkOpAngle::after [3/9] 9/9 tStart=0.25 tEnd=0.124999978 < [6/17] 31/31 tStart=0.125 tEnd=0 < [3/10] 25/25 tStart=0.25 tEnd=0.461228479 F 4
71SkOpAngle::afterPart {{{3.5,3}, {3.25,2.5}}} id=3
72SkOpAngle::afterPart {{{3.5,3}, {4,3}}} id=6
73SkOpAngle::afterPart {{{3.5,3}, {3.92245698,3.84491396}}} id=3
74SkOpAngle::after [3/9] 9/9 tStart=0.25 tEnd=0.124999978 < [6/18] 15/15 tStart=0.125 tEnd=0.153501943 < [3/10] 25/25 tStart=0.25 tEnd=0.461228479 T 4
75SkOpAngle::afterPart {{{3.5,3}, {3.25,2.5}}} id=3
76SkOpAngle::afterPart {{{3.5,3}, {3.38599229,3}}} id=6
77SkOpAngle::afterPart {{{3.5,3}, {3.92245698,3.84491396}}} id=3
78SkOpSegment::sortAngles [3] tStart=0.461228479 [19]
79SkOpAngle::after [3/11] 9/9 tStart=0.461228479 tEnd=0.25 < [5/15] 13/13 tStart=0.31546775 tEnd=0.23289595 < [3/12] 25/25 tStart=0.461228479 tEnd=1 T 4
80SkOpAngle::afterPart {{{3.92245698,3.84491396}, {3.5,3}}} id=3
81SkOpAngle::afterPart {{{3.92245698,3.84491396}, {3.83851397,3.82906267}, {3.74775953,3.80940495}, {3.6512568,3.78673816}}} id=5
82SkOpAngle::afterPart {{{3.92245698,3.84491396}, {5,6}}} id=3
83SkOpAngle::after [3/11] 9/9 tStart=0.461228479 tEnd=0.25 < [5/16] 29/5 tStart=0.31546775 tEnd=1 < [5/15] 13/13 tStart=0.31546775 tEnd=0.23289595 F 4
84SkOpAngle::afterPart {{{3.92245698,3.84491396}, {3.5,3}}} id=3
85SkOpAngle::afterPart {{{3.92245698,3.84491396}, {4.6183568,3.97632344}, {4.84612825,3.84612825}, {4,3}}} id=5
86SkOpAngle::afterPart {{{3.92245698,3.84491396}, {3.83851397,3.82906267}, {3.74775953,3.80940495}, {3.6512568,3.78673816}}} id=5
87SkOpAngle::after [5/15] 13/13 tStart=0.31546775 tEnd=0.23289595 < [5/16] 29/5 tStart=0.31546775 tEnd=1 < [3/12] 25/25 tStart=0.461228479 tEnd=1 F 4
88SkOpAngle::afterPart {{{3.92245698,3.84491396}, {3.83851397,3.82906267}, {3.74775953,3.80940495}, {3.6512568,3.78673816}}} id=5
89SkOpAngle::afterPart {{{3.92245698,3.84491396}, {4.6183568,3.97632344}, {4.84612825,3.84612825}, {4,3}}} id=5
90SkOpAngle::afterPart {{{3.92245698,3.84491396}, {5,6}}} id=3
91SkOpAngle::after [3/12] 25/25 tStart=0.461228479 tEnd=1 < [5/16] 29/5 tStart=0.31546775 tEnd=1 < [3/11] 9/9 tStart=0.461228479 tEnd=0.25 T 4
92SkOpAngle::afterPart {{{3.92245698,3.84491396}, {5,6}}} id=3
93SkOpAngle::afterPart {{{3.92245698,3.84491396}, {4.6183568,3.97632344}, {4.84612825,3.84612825}, {4,3}}} id=5
94SkOpAngle::afterPart {{{3.92245698,3.84491396}, {3.5,3}}} id=3
95SkOpSegment::sortAngles [5] tStart=0.23289595 [16]
96SkOpSegment::sortAngles [5] tStart=0.31546775 [20]
97SkOpSegment::sortAngles [6] tStart=0.125 [22]
98SkOpSegment::sortAngles [6] tStart=0.153501943 [18]
99SkOpSegment::debugShowActiveSpans id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0 (5,6) tEnd=0.385353706 windSum=? windValue=1 oppValue=0
100SkOpSegment::debugShowActiveSpans id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.385353706 (3.6512568,3.78673816) tEnd=0.521306291 windSum=? windValue=1 oppValue=0
101SkOpSegment::debugShowActiveSpans id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.521306291 (3.38599229,3) tEnd=0.617509 windSum=? windValue=1 oppValue=0
102SkOpSegment::debugShowActiveSpans id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.617509 (3.25,2.5) tEnd=1 windSum=? windValue=1 oppValue=0
103SkOpSegment::debugShowActiveSpans id=2 (3.01378202,1.45492136 3,1.45609283 3,1.61940968 3,2) t=0 (3.01378202,1.45492136) tEnd=1 windSum=? windValue=1 oppValue=0
104SkOpSegment::debugShowActiveSpans id=3 (3,2 5,6) t=0 (3,2) tEnd=0.124999978 windSum=? windValue=1 oppValue=0
105SkOpSegment::debugShowActiveSpans id=3 (3,2 5,6) t=0.124999978 (3.25,2.5) tEnd=0.25 windSum=? windValue=1 oppValue=0
106SkOpSegment::debugShowActiveSpans id=3 (3,2 5,6) t=0.25 (3.5,3) tEnd=0.461228479 windSum=? windValue=1 oppValue=0
107SkOpSegment::debugShowActiveSpans id=3 (3,2 5,6) t=0.461228479 (3.92245698,3.84491396) tEnd=1 windSum=? windValue=1 oppValue=0
108SkOpSegment::debugShowActiveSpans id=4 (0,3 0.763932049,3 1.81966019,3.29179597 2.72135973,3.54101968) t=0 (0,3) tEnd=1 windSum=? windValue=1 oppValue=0
109SkOpSegment::debugShowActiveSpans id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0 (2.72135973,3.54101968) tEnd=0.23289595 windSum=? windValue=1 oppValue=0
110SkOpSegment::debugShowActiveSpans id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.23289595 (3.6512568,3.78673816) tEnd=0.31546775 windSum=? windValue=1 oppValue=0
111SkOpSegment::debugShowActiveSpans id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.31546775 (3.92245698,3.84491396) tEnd=1 windSum=? windValue=1 oppValue=0
112SkOpSegment::debugShowActiveSpans id=6 (4,3 0,3) t=0 (4,3) tEnd=0.125 windSum=? windValue=1 oppValue=0
113SkOpSegment::debugShowActiveSpans id=6 (4,3 0,3) t=0.125 (3.5,3) tEnd=0.153501943 windSum=? windValue=1 oppValue=0
114SkOpSegment::debugShowActiveSpans id=6 (4,3 0,3) t=0.153501943 (3.38599229,3) tEnd=1 windSum=? windValue=1 oppValue=0
caryclark65f55312014-11-13 06:58:52 -0800115SkOpSegment::findTop
caryclark1049f122015-04-20 08:31:59 -0700116SkOpAngle::dumpOne [1/21] next=2/22 sect=1/25 s=1 [2] e=0.617509 [13] sgn=1 windVal=1 windSum=?
117SkOpAngle::dumpOne [2/22] next=1/21 sect=17/21 s=0 [3] e=1 [4] sgn=-1 windVal=1 windSum=?
118SkOpSegment::markWinding id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.617509 [13] (3.25,2.5) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
caryclark65f55312014-11-13 06:58:52 -0800119SkOpSegment::nextChase mismatched signs
caryclark1049f122015-04-20 08:31:59 -0700120SkOpSegment::markWinding id=2 (3.01378202,1.45492136 3,1.45609283 3,1.61940968 3,2) t=0 [3] (3.01378202,1.45492136) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
121SkOpSegment::markWinding id=3 (3,2 5,6) t=0 [5] (3,2) tEnd=0.124999978 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
122SkOpSegment::markWinding id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.617509 [13] (3.25,2.5) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
123SkOpSegment::activeOp id=1 t=0.617509 tEnd=1 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
caryclark65f55312014-11-13 06:58:52 -0800124SkOpSegment::nextChase mismatched signs
caryclark65f55312014-11-13 06:58:52 -0800125SkOpSegment::findNextOp simple
caryclark1049f122015-04-20 08:31:59 -0700126SkOpSegment::markDone id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.617509 [13] (3.25,2.5) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
127bridgeOp current id=1 from=(3.25,2.5) to=(3.01378202,1.45492136)
128path.moveTo(3.25,2.5);
129path.cubicTo(3.09514761,1.88059044, 3.03621221,1.45301485, 3.01378202,1.45492136);
caryclark65f55312014-11-13 06:58:52 -0800130SkOpSegment::findNextOp simple
caryclark1049f122015-04-20 08:31:59 -0700131SkOpSegment::markDone id=2 (3.01378202,1.45492136 3,1.45609283 3,1.61940968 3,2) t=0 [3] (3.01378202,1.45492136) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
132bridgeOp current id=2 from=(3.01378202,1.45492136) to=(3,2)
133path.cubicTo(3,1.45609283, 3,1.61940968, 3,2);
134SkOpSegment::markWinding id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.521306291 [17] (3.38599229,3) tEnd=0.617509 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
135SkOpSegment::markAngle last segment=1 span=17 windSum=-2
136SkOpSegment::markWinding id=3 (3,2 5,6) t=0.124999978 [14] (3.25,2.5) tEnd=0.25 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
137SkOpSegment::markAngle last segment=3 span=21 windSum=?
138SkOpSegment::findNextOp
139SkOpAngle::dumpOne [3/7] next=1/5 sect=9/9 s=0.124999978 [14] e=0 [5] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0
140SkOpAngle::dumpOne [1/5] next=3/8 sect=25/25 s=0.617509 [13] e=0.521306291 [17] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=0
141SkOpAngle::dumpOne [3/8] next=1/6 sect=25/25 s=0.124999978 [14] e=0.25 [21] sgn=-1 windVal=1 windSum=-2 oppVal=0 oppSum=0
142SkOpAngle::dumpOne [1/6] next=3/7 sect=9/9 s=0.617509 [13] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 done
143SkOpSegment::activeOp id=1 t=0.617509 tEnd=0.521306291 op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
144SkOpSegment::markDone id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.521306291 [17] (3.38599229,3) tEnd=0.617509 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
145SkOpSegment::findNextOp chase.append segment=1 span=17 windSum=-2
146SkOpSegment::activeOp id=3 t=0.124999978 tEnd=0.25 op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
147SkOpSegment::markDone id=3 (3,2 5,6) t=0.124999978 [14] (3.25,2.5) tEnd=0.25 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
148SkOpSegment::findNextOp chase.append segment=3 span=21 windSum=-2147483647
149SkOpSegment::activeOp id=1 t=0.617509 tEnd=1 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
150SkOpSegment::markDone id=3 (3,2 5,6) t=0 [5] (3,2) tEnd=0.124999978 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
151SkOpSegment::findNextOp from:[3] to:[1] start=7692876 end=11466464
152bridgeOp current id=3 from=(3,2) to=(3.25,2.5)
153path.lineTo(3.25,2.5);
caryclark54359292015-03-26 07:52:43 -0700154path.close();
caryclark1049f122015-04-20 08:31:59 -0700155SkOpSegment::markWinding id=6 (4,3 0,3) t=0.125 [22] (3.5,3) tEnd=0.153501943 newWindSum=1 newOppSum=-2 oppSum=? windSum=? windValue=1 oppValue=0
156SkOpSegment::markAngle last segment=6 span=18 windSum=?
157SkOpSegment::markWinding id=3 (3,2 5,6) t=0.25 [21] (3.5,3) tEnd=0.461228479 newWindSum=-2 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
158SkOpSegment::markAngle last segment=3 span=19 windSum=?
159SkOpSegment::markWinding id=6 (4,3 0,3) t=0 [11] (4,3) tEnd=0.125 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
160SkOpSegment::markWinding id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.31546775 [20] (3.92245698,3.84491396) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
161SkOpSegment::markAngle last segment=5 span=20 windSum=1
162SkOpSegment::debugShowActiveSpans id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0 (5,6) tEnd=0.385353706 windSum=? windValue=1 oppValue=0
163SkOpSegment::debugShowActiveSpans id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.385353706 (3.6512568,3.78673816) tEnd=0.521306291 windSum=? windValue=1 oppValue=0
164SkOpSegment::debugShowActiveSpans id=3 (3,2 5,6) t=0.25 (3.5,3) tEnd=0.461228479 windSum=-2 windValue=1 oppValue=0
165SkOpSegment::debugShowActiveSpans id=3 (3,2 5,6) t=0.461228479 (3.92245698,3.84491396) tEnd=1 windSum=? windValue=1 oppValue=0
166SkOpSegment::debugShowActiveSpans id=4 (0,3 0.763932049,3 1.81966019,3.29179597 2.72135973,3.54101968) t=0 (0,3) tEnd=1 windSum=? windValue=1 oppValue=0
167SkOpSegment::debugShowActiveSpans id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0 (2.72135973,3.54101968) tEnd=0.23289595 windSum=? windValue=1 oppValue=0
168SkOpSegment::debugShowActiveSpans id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.23289595 (3.6512568,3.78673816) tEnd=0.31546775 windSum=? windValue=1 oppValue=0
169SkOpSegment::debugShowActiveSpans id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.31546775 (3.92245698,3.84491396) tEnd=1 windSum=1 windValue=1 oppValue=0
170SkOpSegment::debugShowActiveSpans id=6 (4,3 0,3) t=0 (4,3) tEnd=0.125 windSum=1 windValue=1 oppValue=0
171SkOpSegment::debugShowActiveSpans id=6 (4,3 0,3) t=0.125 (3.5,3) tEnd=0.153501943 windSum=1 windValue=1 oppValue=0
172SkOpSegment::debugShowActiveSpans id=6 (4,3 0,3) t=0.153501943 (3.38599229,3) tEnd=1 windSum=? windValue=1 oppValue=0
173SkOpSegment::activeOp id=6 t=0.125 tEnd=0.153501943 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
174SkOpSegment::markWinding id=6 (4,3 0,3) t=0.153501943 [18] (3.38599229,3) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
175SkOpSegment::markWinding id=4 (0,3 0.763932049,3 1.81966019,3.29179597 2.72135973,3.54101968) t=0 [7] (0,3) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
176SkOpSegment::markWinding id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0 [9] (2.72135973,3.54101968) tEnd=0.23289595 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
177SkOpSegment::markAngle last segment=5 span=16 windSum=?
178SkOpSegment::markWinding id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.385353706 [15] (3.6512568,3.78673816) tEnd=0.521306291 newWindSum=-2 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
179SkOpSegment::markAngle last segment=1 span=15 windSum=-2
180SkOpSegment::findNextOp
181SkOpAngle::dumpOne [6/19] next=1/4 sect=31/31 s=0.153501943 [18] e=0.125 [22] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-2 operand
182SkOpAngle::dumpOne [1/4] next=6/20 sect=9/9 s=0.521306291 [17] e=0.617509 [13] sgn=-1 windVal=1 windSum=-2 oppVal=0 oppSum=0 done
183SkOpAngle::dumpOne [6/20] next=1/3 sect=15/15 s=0.153501943 [18] e=1 [12] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=-1 operand
184SkOpAngle::dumpOne [1/3] next=6/19 sect=25/25 s=0.521306291 [17] e=0.385353706 [15] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=1
185SkOpSegment::activeOp id=1 t=0.521306291 tEnd=0.617509 op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
186SkOpSegment::activeOp id=6 t=0.153501943 tEnd=1 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
187SkOpSegment::findNextOp chase.append segment=5 span=16 windSum=-2147483647
188SkOpSegment::activeOp id=1 t=0.521306291 tEnd=0.385353706 op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
189SkOpSegment::markDone id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0.385353706 [15] (3.6512568,3.78673816) tEnd=0.521306291 newWindSum=-2 newOppSum=1 oppSum=1 windSum=-2 windValue=1 oppValue=0
190SkOpSegment::findNextOp chase.append segment=1 span=15 windSum=-2
191SkOpSegment::markDone id=6 (4,3 0,3) t=0.125 [22] (3.5,3) tEnd=0.153501943 newWindSum=1 newOppSum=-2 oppSum=-2 windSum=1 windValue=1 oppValue=0
192SkOpSegment::findNextOp from:[6] to:[6] start=7693356 end=7692756
193bridgeOp current id=6 from=(3.5,3) to=(3.38599229,3)
caryclark65f55312014-11-13 06:58:52 -0800194SkOpSegment::findNextOp simple
caryclark1049f122015-04-20 08:31:59 -0700195SkOpSegment::markDone id=6 (4,3 0,3) t=0.153501943 [18] (3.38599229,3) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
196bridgeOp current id=6 from=(3.38599229,3) to=(0,3)
caryclark65f55312014-11-13 06:58:52 -0800197SkOpSegment::findNextOp simple
caryclark1049f122015-04-20 08:31:59 -0700198SkOpSegment::markDone id=4 (0,3 0.763932049,3 1.81966019,3.29179597 2.72135973,3.54101968) t=0 [7] (0,3) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
199bridgeOp current id=4 from=(0,3) to=(2.72135973,3.54101968)
200path.moveTo(3.5,3);
201path.lineTo(0,3);
202path.cubicTo(0.763932049,3, 1.81966019,3.29179597, 2.72135973,3.54101968);
203SkOpSegment::markWinding id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0 [1] (5,6) tEnd=0.385353706 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
204SkOpSegment::markWinding id=3 (3,2 5,6) t=0.461228479 [19] (3.92245698,3.84491396) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
205SkOpSegment::markAngle last segment=3 span=19 windSum=-2
206SkOpSegment::markWinding id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.23289595 [16] (3.6512568,3.78673816) tEnd=0.31546775 newWindSum=1 newOppSum=-2 oppSum=? windSum=? windValue=1 oppValue=0
207SkOpSegment::markAngle last segment=5 span=20 windSum=1
208SkOpSegment::findNextOp
209SkOpAngle::dumpOne [5/13] next=1/1 sect=13/13 s=0.23289595 [16] e=0 [9] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-1 operand
210SkOpAngle::dumpOne [1/1] next=5/14 sect=25/25 s=0.385353706 [15] e=0 [1] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=0
211SkOpAngle::dumpOne [5/14] next=1/2 sect=29/29 s=0.23289595 [16] e=0.31546775 [20] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=-2 operand
212SkOpAngle::dumpOne [1/2] next=5/13 sect=9/9 s=0.385353706 [15] e=0.521306291 [17] sgn=-1 windVal=1 windSum=-2 oppVal=0 oppSum=1 done
213SkOpSegment::activeOp id=1 t=0.385353706 tEnd=0 op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
214SkOpSegment::markDone id=1 (5,6 3.38059044,4.38059044 3.07242441,1.44993687 3.01378202,1.45492136) t=0 [1] (5,6) tEnd=0.385353706 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
215SkOpSegment::markDone id=3 (3,2 5,6) t=0.461228479 [19] (3.92245698,3.84491396) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
216SkOpSegment::findNextOp chase.append segment=3 span=19 windSum=-2
217SkOpSegment::activeOp id=5 t=0.23289595 tEnd=0.31546775 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
218SkOpSegment::findNextOp chase.append segment=5 span=20 windSum=1
219SkOpSegment::activeOp id=1 t=0.385353706 tEnd=0.521306291 op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
220SkOpSegment::markDone id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0 [9] (2.72135973,3.54101968) tEnd=0.23289595 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
221SkOpSegment::findNextOp from:[5] to:[5] start=7693164 end=7693548
222bridgeOp current id=5 from=(2.72135973,3.54101968) to=(3.6512568,3.78673816)
223path.cubicTo(3.06115031,3.63493538, 3.37906837,3.72280598, 3.6512568,3.78673816);
224SkOpSegment::findNextOp
225SkOpAngle::dumpOne [5/15] next=3/12 sect=13/13 s=0.31546775 [20] e=0.23289595 [16] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-2 operand
226SkOpAngle::dumpOne [3/12] next=5/16 sect=25/25 s=0.461228479 [19] e=1 [6] sgn=-1 windVal=1 windSum=-2 oppVal=0 oppSum=0 done
227SkOpAngle::dumpOne [5/16] next=3/11 sect=29/5 s=0.31546775 [20] e=1 [10] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=-1 operand
228SkOpAngle::dumpOne [3/11] next=5/15 sect=9/9 s=0.461228479 [19] e=0.25 [21] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=1
229SkOpSegment::activeOp id=3 t=0.461228479 tEnd=1 op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
230SkOpSegment::activeOp id=5 t=0.31546775 tEnd=1 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
231SkOpSegment::activeOp id=3 t=0.461228479 tEnd=0.25 op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
232SkOpSegment::markDone id=3 (3,2 5,6) t=0.25 [21] (3.5,3) tEnd=0.461228479 newWindSum=-2 newOppSum=1 oppSum=1 windSum=-2 windValue=1 oppValue=0
233SkOpSegment::markDone id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.23289595 [16] (3.6512568,3.78673816) tEnd=0.31546775 newWindSum=1 newOppSum=-2 oppSum=-2 windSum=1 windValue=1 oppValue=0
234SkOpSegment::findNextOp from:[5] to:[5] start=7693548 end=7692540
235bridgeOp current id=5 from=(3.6512568,3.78673816) to=(3.92245698,3.84491396)
236path.cubicTo(3.74775958,3.80940485, 3.83851385,3.8290627, 3.92245698,3.84491396);
caryclark65f55312014-11-13 06:58:52 -0800237SkOpSegment::findNextOp simple
caryclark1049f122015-04-20 08:31:59 -0700238SkOpSegment::markDone id=5 (2.72135973,3.54101968 4.18033981,3.9442718 5.23606777,4.23606777 4,3) t=0.31546775 [20] (3.92245698,3.84491396) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
239bridgeOp current id=5 from=(3.92245698,3.84491396) to=(4,3)
240path.cubicTo(4.6183567,3.97632337, 4.84612846,3.84612823, 4,3);
241SkOpSegment::findNextOp
242SkOpAngle::dumpOne [6/17] next=3/9 sect=31/31 s=0.125 [22] e=0 [11] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-1 operand
243SkOpAngle::dumpOne [3/9] next=6/18 sect=9/9 s=0.25 [21] e=0.124999978 [14] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=0 done
244SkOpAngle::dumpOne [6/18] next=3/10 sect=15/15 s=0.125 [22] e=0.153501943 [18] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=-2 done operand
245SkOpAngle::dumpOne [3/10] next=6/17 sect=25/25 s=0.25 [21] e=0.461228479 [19] sgn=-1 windVal=1 windSum=-2 oppVal=0 oppSum=1 done
246SkOpSegment::activeOp id=3 t=0.25 tEnd=0.124999978 op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
247SkOpSegment::activeOp id=6 t=0.125 tEnd=0.153501943 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
248SkOpSegment::activeOp id=3 t=0.25 tEnd=0.461228479 op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
249SkOpSegment::markDone id=6 (4,3 0,3) t=0 [11] (4,3) tEnd=0.125 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0
250SkOpSegment::findNextOp from:[6] to:[6] start=7693740 end=7693356
251bridgeOp current id=6 from=(4,3) to=(3.5,3)
252path.lineTo(3.5,3);
caryclark54359292015-03-26 07:52:43 -0700253path.close();
caryclarkdac1d172014-06-17 05:15:38 -0700254</div>
caryclark54359292015-03-26 07:52:43 -0700255
caryclarkdac1d172014-06-17 05:15:38 -0700256</div>
257
258<script type="text/javascript">
259
260var testDivs = [
caryclark1049f122015-04-20 08:31:59 -0700261 cubicOp132,
caryclarkdac1d172014-06-17 05:15:38 -0700262];
263
264var decimal_places = 3; // make this 3 to show more precision
265
266var tests = [];
267var testLines = [];
268var testTitles = [];
269var testIndex = 0;
270var ctx;
271
272var xmin, xmax, focusXmin, focusXmax;
273var ymin, ymax, focusYmin, focusYmax;
274var scale;
275var mouseX, mouseY;
276var srcLeft, srcTop;
277var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700278var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700279var curveT = 0;
280
281var pt_labels = 2;
282var collect_bounds = false;
283var control_lines = 0;
284var curve_t = false;
285var debug_xy = 1;
286var focus_enabled = false;
287var focus_on_selection = false;
288var step_limit = 0;
289var draw_active = false;
290var draw_add = false;
291var draw_angle = 0;
292var draw_deriviatives = 0;
293var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700294var draw_id = false;
295var draw_intersection = 0;
296var draw_intersectT = false;
297var draw_legend = true;
298var draw_log = false;
299var draw_mark = false;
300var draw_midpoint = false;
301var draw_op = 0;
302var draw_sequence = false;
303var draw_sort = 0;
304var draw_path = 3;
305var draw_computed = 0;
306var retina_scale = !!window.devicePixelRatio;
307
308var activeCount = 0;
309var addCount = 0;
310var angleCount = 0;
311var opCount = 0;
312var sectCount = 0;
313var sortCount = 0;
314var markCount = 0;
315var activeMax = 0;
316var addMax = 0;
317var angleMax = 0;
318var sectMax = 0;
319var sectMax2 = 0;
320var sortMax = 0;
321var markMax = 0;
322var opMax = 0;
323var stepMax = 0;
324var lastIndex = 0;
325var hasPath = false;
326var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700327var angleBetween = false;
328var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700329
330var firstActiveSpan = -1;
331var logStart = -1;
332var logRange = 0;
333
334var SPAN_ID = 0;
335var SPAN_X1 = SPAN_ID + 1;
336var SPAN_Y1 = SPAN_X1 + 1;
337var SPAN_X2 = SPAN_Y1 + 1;
338var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700339
caryclarkdac1d172014-06-17 05:15:38 -0700340var SPAN_L_T = SPAN_Y2 + 1;
341var SPAN_L_TX = SPAN_L_T + 1;
342var SPAN_L_TY = SPAN_L_TX + 1;
343var SPAN_L_TEND = SPAN_L_TY + 1;
344var SPAN_L_OTHER = SPAN_L_TEND + 1;
345var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
346var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
347var SPAN_L_SUM = SPAN_L_OTHERI + 1;
348var SPAN_L_VAL = SPAN_L_SUM + 1;
349var SPAN_L_OPP = SPAN_L_VAL + 1;
350
351var SPAN_X3 = SPAN_Y2 + 1;
352var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700353
caryclarkdac1d172014-06-17 05:15:38 -0700354var SPAN_Q_T = SPAN_Y3 + 1;
355var SPAN_Q_TX = SPAN_Q_T + 1;
356var SPAN_Q_TY = SPAN_Q_TX + 1;
357var SPAN_Q_TEND = SPAN_Q_TY + 1;
358var SPAN_Q_OTHER = SPAN_Q_TEND + 1;
359var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
360var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
361var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
362var SPAN_Q_VAL = SPAN_Q_SUM + 1;
363var SPAN_Q_OPP = SPAN_Q_VAL + 1;
364
caryclark1049f122015-04-20 08:31:59 -0700365var SPAN_K_W = SPAN_Y3 + 1;
366var SPAN_K_T = SPAN_K_W + 1;
367var SPAN_K_TX = SPAN_K_T + 1;
368var SPAN_K_TY = SPAN_K_TX + 1;
369var SPAN_K_TEND = SPAN_K_TY + 1;
370var SPAN_K_OTHER = SPAN_K_TEND + 1;
371var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
372var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
373var SPAN_K_SUM = SPAN_K_OTHERI + 1;
374var SPAN_K_VAL = SPAN_K_SUM + 1;
375var SPAN_K_OPP = SPAN_K_VAL + 1;
376
caryclarkdac1d172014-06-17 05:15:38 -0700377var SPAN_X4 = SPAN_Y3 + 1;
378var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700379
caryclarkdac1d172014-06-17 05:15:38 -0700380var SPAN_C_T = SPAN_Y4 + 1;
381var SPAN_C_TX = SPAN_C_T + 1;
382var SPAN_C_TY = SPAN_C_TX + 1;
383var SPAN_C_TEND = SPAN_C_TY + 1;
384var SPAN_C_OTHER = SPAN_C_TEND + 1;
385var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
386var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
387var SPAN_C_SUM = SPAN_C_OTHERI + 1;
388var SPAN_C_VAL = SPAN_C_SUM + 1;
389var SPAN_C_OPP = SPAN_C_VAL + 1;
390
391var ACTIVE_LINE_SPAN = 1;
392var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700393var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
394var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700395
396var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
397var ADD_LINETO = ADD_MOVETO + 1;
398var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700399var ADD_CONICTO = ADD_QUADTO + 1;
400var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700401var ADD_CLOSE = ADD_CUBICTO + 1;
402var ADD_FILL = ADD_CLOSE + 1;
403
404var PATH_LINE = ADD_FILL + 1;
405var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700406var PATH_CONIC = PATH_QUAD + 1;
407var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700408
409var INTERSECT_LINE = PATH_CUBIC + 1;
410var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
411var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
412var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
413var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
414var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
415var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
416var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
417var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700418var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
419var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
420var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
421var INTERSECT_CONIC = INTERSECT_CONIC_LINE_NO + 1;
422var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
423var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
424var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700425var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
426var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
427var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
428var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
429var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
430var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
431var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
432var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
433var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
434var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
435var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
436var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
437var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
438var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
439// FIXME: add cubic 5- 9
440var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
441
442var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
443var SORT_BINARY = SORT_UNARY + 1;
444
445var OP_DIFFERENCE = SORT_BINARY + 1;
446var OP_INTERSECT = OP_DIFFERENCE + 1;
447var OP_UNION = OP_INTERSECT + 1;
448var OP_XOR = OP_UNION + 1;
449
450var MARK_LINE = OP_XOR + 1;
451var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700452var MARK_CONIC = MARK_QUAD + 1;
453var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700454var MARK_DONE_LINE = MARK_CUBIC + 1;
455var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700456var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
457var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700458var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
459var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700460var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
461var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700462var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
463var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700464var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
465var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700466var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
467var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700468var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
469var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700470var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
471var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700472var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
473var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700474var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
475
476var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
477var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
478
479var ANGLE_AFTER = COMPUTED_SET_2;
caryclark54359292015-03-26 07:52:43 -0700480var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700481
caryclark54359292015-03-26 07:52:43 -0700482var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700483
484var FRAG_TYPE_LAST = ACTIVE_OP;
485
486var REC_TYPE_UNKNOWN = -1;
487var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700488var REC_TYPE_PATH2 = 1;
489var REC_TYPE_SECT = 2;
490var REC_TYPE_ACTIVE = 3;
491var REC_TYPE_ADD = 4;
492var REC_TYPE_SORT = 5;
493var REC_TYPE_OP = 6;
494var REC_TYPE_MARK = 7;
495var REC_TYPE_COMPUTED = 8;
496var REC_TYPE_COIN = 9;
497var REC_TYPE_ANGLE = 10;
498var REC_TYPE_ACTIVE_OP = 11;
499var REC_TYPE_AFTERPART = 12;
500var REC_TYPE_LAST = REC_TYPE_AFTERPART;
caryclarkdac1d172014-06-17 05:15:38 -0700501
502function strs_to_nums(strs) {
503 var result = [];
504 for (var idx = 1; idx < strs.length; ++idx) {
505 var str = strs[idx];
506 var num = parseFloat(str);
507 if (isNaN(num)) {
508 result.push(str);
509 } else {
510 result.push(num);
511 }
512 }
513 return result;
514}
515
516function filter_str_by(id, str, regex, array) {
517 if (regex.test(str)) {
518 var strs = regex.exec(str);
519 var result = strs_to_nums(strs);
520 array.push(id);
521 array.push(result);
522 return true;
523 }
524 return false;
525}
526
527function construct_regexp2(pattern) {
528 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
529 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
530 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700531 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700532 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
533 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
534 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700535 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700536 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
537 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
538 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700539 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700540 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700541 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700542 escape = escape.replace(/NUM/g, "(-?\\d+)");
543 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
544 return new RegExp(escape, 'i');
545}
546
547function construct_regexp2c(pattern) {
548 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
549 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700550 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700551 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700552 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
553 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700554 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700555 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700556 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
caryclark54359292015-03-26 07:52:43 -0700557 escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700558 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700559 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700560 escape = escape.replace(/OPER/g, "[a-z]+");
561 escape = escape.replace(/PATH/g, "pathB?");
562 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700563 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700564 escape = escape.replace(/NUM/g, "(-?\\d+)");
565 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
566 return new RegExp(escape, 'i');
567}
568
569function match_regexp(str, lineNo, array, id, pattern) {
570 var regex = construct_regexp2(pattern);
571 if (filter_str_by(id, str, regex, array)) {
572 return true;
573 }
574 regex = construct_regexp2c(pattern);
575 return filter_str_by(id, str, regex, array);
576}
577
578function endsWith(str, suffix) {
579 return str.indexOf(suffix, str.length - suffix.length) !== -1;
580}
581
582function parse_all(test) {
583 var lines = test.match(/[^\r\n]+/g);
584 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
585 var record = [];
586 var recType = REC_TYPE_UNKNOWN;
587 var lastLineNo;
588 var moveX, moveY;
589 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
590 var line = lines[lineNo];
591 if (line.length == 0) {
592 continue;
593 }
594 var opStart = "SkOpSegment::";
595 if (line.lastIndexOf(opStart, 0) === 0) {
596 line = line.substr(opStart.length);
597 }
598 var angleStart = "SkOpAngle::";
599 if (line.lastIndexOf(angleStart, 0) === 0) {
600 line = line.substr(angleStart.length);
601 }
caryclark54359292015-03-26 07:52:43 -0700602 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
603 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclarkdac1d172014-06-17 05:15:38 -0700604 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
caryclark54359292015-03-26 07:52:43 -0700605 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700606 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
607 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
608 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
609 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
610 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
611 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
612 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
613 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
614 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
615 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700616 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700617 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
618 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
619 : REC_TYPE_UNKNOWN;
620 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
621 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
622 if (recType != REC_TYPE_UNKNOWN) {
623 records.push(recType);
624 records.push(lastLineNo);
625 records.push(record);
626 }
627 record = [];
628 recType = type;
629 lastLineNo = lineNo;
630 }
631 var found = false;
632 switch (recType) {
633 case REC_TYPE_ACTIVE:
634 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark54359292015-03-26 07:52:43 -0700635" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700636 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark54359292015-03-26 07:52:43 -0700637" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclark1049f122015-04-20 08:31:59 -0700638 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
639" id=IDX CONIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700640 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark54359292015-03-26 07:52:43 -0700641" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL windSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700642 );
643 break;
644 case REC_TYPE_ACTIVE_OP:
645 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
646" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
647 );
648 break;
649 case REC_TYPE_ADD:
650 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
651 moveX = record[1][0];
652 moveY = record[1][1];
653 found = true;
654 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
655 record[1].unshift(moveY);
656 record[1].unshift(moveX);
657 moveX = record[1][2];
658 moveY = record[1][3];
659 found = true;
660 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
661 record[1].unshift(moveY);
662 record[1].unshift(moveX);
663 moveX = record[1][4];
664 moveY = record[1][5];
665 found = true;
caryclark1049f122015-04-20 08:31:59 -0700666 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
667 record[1].unshift(moveY);
668 record[1].unshift(moveX);
669 moveX = record[1][4];
670 moveY = record[1][5];
671 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700672 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
673 record[1].unshift(moveY);
674 record[1].unshift(moveX);
675 moveX = record[1][6];
676 moveY = record[1][7];
677 found = true;
678 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
679 found = true;
680 } else {
681 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
682 }
683 break;
caryclark54359292015-03-26 07:52:43 -0700684 case REC_TYPE_AFTERPART:
685 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL")
686 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL")
caryclark1049f122015-04-20 08:31:59 -0700687 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL")
caryclark54359292015-03-26 07:52:43 -0700688 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL")
689 break;
caryclarkdac1d172014-06-17 05:15:38 -0700690 case REC_TYPE_ANGLE:
691 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
caryclarkdac1d172014-06-17 05:15:38 -0700692"[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");
693 break;
694 case REC_TYPE_COIN:
695 found = true;
696 break;
697 case REC_TYPE_COMPUTED:
698 found = line == "computed quadratics given"
699 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
700 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
701 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -0700702 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -0700703 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
704 );
705 break;
706 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700707 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
708 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700709 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -0700710 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
711 );
712 break;
713 case REC_TYPE_PATH2:
714 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
715 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -0700716 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -0700717 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -0700718 );
719 break;
720 case REC_TYPE_SECT:
721 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
722" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
723 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
724" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
725 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
726" no intersect LINE_VAL LINE_VAL"
727 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
728" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
729 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
730" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
731 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
732" no intersect QUAD_VAL LINE_VAL"
733 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
734" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
735 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
736" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
737 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
738" no intersect QUAD_VAL QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700739 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
740" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
741 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
742" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
743 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
744" no intersect CONIC_VAL LINE_VAL"
745 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
746" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
747 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
748" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
749 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
750" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -0700751 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
752" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
753 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
754" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
755 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
756" 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"
757 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
758" no intersect CUBIC_VAL LINE_VAL"
759 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
760" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
761 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
762" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
763 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
764" 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"
765 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
766" 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"
767 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
768" no intersect CUBIC_VAL QUAD_VAL"
769 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
770" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
771 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
772" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
773 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
774" 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"
775 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
776" 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"
777 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
778" no intersect CUBIC_VAL CUBIC_VAL"
779 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
780" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
781 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
782" no self intersect CUBIC_VAL"
783 );
784 break;
785 case REC_TYPE_SORT:
786 var hasDone = / done/.test(line);
787 var hasUnorderable = / unorderable/.test(line);
788 var hasSmall = / small/.test(line);
789 var hasTiny = / tiny/.test(line);
790 var hasOperand = / operand/.test(line);
791 var hasStop = / stop/.test(line);
792 line.replace(/[ a-z]+$/, "");
793 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
794" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
795 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
796" [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"
797 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
798" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
799 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
800" [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"
801 );
802 if (found) {
803 record[1].push(hasDone);
804 record[1].push(hasUnorderable);
805 record[1].push(hasSmall);
806 record[1].push(hasTiny);
807 record[1].push(hasOperand);
808 record[1].push(hasStop);
809 }
810 break;
811 case REC_TYPE_MARK:
812 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700813" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700814 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700815" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700816 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
817" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700818 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -0700819" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
820 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
821" 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"
822 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
823" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
caryclark1049f122015-04-20 08:31:59 -0700824 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
825" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
caryclark54359292015-03-26 07:52:43 -0700826 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
827" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT"
caryclarkdac1d172014-06-17 05:15:38 -0700828 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
829" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
830 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
831" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700832 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
833" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700834 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
835" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700836 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -0700837" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -0700838 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
839" last segment=IDX span=IDX windSum=OPT");
caryclarkdac1d172014-06-17 05:15:38 -0700840 break;
841 case REC_TYPE_OP:
842 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
843 || line.lastIndexOf("operator<", 0) === 0) {
844 found = true;
845 break;
846 }
caryclark54359292015-03-26 07:52:43 -0700847 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -0700848 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -0700849 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -0700850 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
851 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
852 );
853 break;
854 case REC_TYPE_UNKNOWN:
855 found = true;
856 break;
857 }
858 if (!found) {
859 console.log(line + " [" + lineNo + "] of type " + type + " not found");
860 }
861 }
862 if (recType != REC_TYPE_UNKNOWN) {
863 records.push(recType);
864 records.push(lastLineNo);
865 records.push(record);
866 }
867 if (records.length >= 1) {
868 tests[testIndex] = records;
869 testLines[testIndex] = lines;
870 }
871}
872
873function init(test) {
874 var canvas = document.getElementById('canvas');
875 if (!canvas.getContext) return;
876 ctx = canvas.getContext('2d');
877 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
878 var unscaledWidth = window.innerWidth - 20;
879 var unscaledHeight = window.innerHeight - 20;
880 screenWidth = unscaledWidth;
881 screenHeight = unscaledHeight;
882 canvas.width = unscaledWidth * resScale;
883 canvas.height = unscaledHeight * resScale;
884 canvas.style.width = unscaledWidth + 'px';
885 canvas.style.height = unscaledHeight + 'px';
886 if (resScale != 1) {
887 ctx.scale(resScale, resScale);
888 }
889 xmin = Infinity;
890 xmax = -Infinity;
891 ymin = Infinity;
892 ymax = -Infinity;
893 hasPath = hasComputedPath = false;
894 firstActiveSpan = -1;
895 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
896 var recType = test[tIndex];
897 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
898 console.log("unknown rec type: " + recType);
899 throw "stop execution";
900 }
901 var records = test[tIndex + 2];
902 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
903 var fragType = records[recordIndex];
904 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
905 console.log("unknown in range frag type: " + fragType);
906 throw "stop execution";
907 }
908 var frags = records[recordIndex + 1];
909 var first = 0;
910 var last = -1;
911 var first2 = 0;
912 var last2 = 0;
913 switch (recType) {
914 case REC_TYPE_COMPUTED:
915 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
916 break;
917 }
918 hasComputedPath = true;
919 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700920 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -0700921 switch (fragType) {
922 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -0700923 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -0700924 break;
caryclark1049f122015-04-20 08:31:59 -0700925 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -0700926 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -0700927 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -0700928 break;
929 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -0700930 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -0700931 break;
932 default:
933 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
934 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
935 throw "stop execution";
936 }
937 if (recType == REC_TYPE_PATH) {
938 hasPath = true;
939 }
940 break;
caryclark54359292015-03-26 07:52:43 -0700941 case REC_TYPE_PATH2:
942 first = 1;
943 switch (fragType) {
944 case PATH_LINE:
945 last = 5;
946 break;
caryclark1049f122015-04-20 08:31:59 -0700947 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -0700948 case PATH_QUAD:
949 last = 7;
950 break;
951 case PATH_CUBIC:
952 last = 9;
953 break;
954 default:
955 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
956 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
957 throw "stop execution";
958 }
959 if (recType == REC_TYPE_PATH2) {
960 hasPath = true;
961 }
962 break;
caryclarkdac1d172014-06-17 05:15:38 -0700963 case REC_TYPE_ACTIVE:
964 if (firstActiveSpan < 0) {
965 firstActiveSpan = tIndex;
966 }
967 first = 1;
968 switch (fragType) {
969 case ACTIVE_LINE_SPAN:
970 last = 5;
971 break;
caryclark1049f122015-04-20 08:31:59 -0700972 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -0700973 case ACTIVE_QUAD_SPAN:
974 last = 7;
975 break;
976 case ACTIVE_CUBIC_SPAN:
977 last = 9;
978 break;
979 default:
980 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
981 throw "stop execution";
982 }
983 break;
984 case REC_TYPE_ADD:
985 switch (fragType) {
986 case ADD_MOVETO:
987 break;
988 case ADD_LINETO:
989 last = 4;
990 break;
caryclark1049f122015-04-20 08:31:59 -0700991 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -0700992 case ADD_QUADTO:
993 last = 6;
994 break;
995 case ADD_CUBICTO:
996 last = 8;
997 break;
998 case ADD_CLOSE:
999 case ADD_FILL:
1000 break;
1001 default:
1002 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1003 throw "stop execution";
1004 }
1005 break;
caryclark54359292015-03-26 07:52:43 -07001006 case REC_TYPE_AFTERPART:
1007 switch (fragType) {
1008 case PATH_LINE:
1009 last = 4;
1010 break;
caryclark1049f122015-04-20 08:31:59 -07001011 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001012 case PATH_QUAD:
1013 last = 6;
1014 break;
1015 case PATH_CUBIC:
1016 last = 8;
1017 break;
1018 default:
1019 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1020 throw "stop execution";
1021 }
1022 break;
caryclarkdac1d172014-06-17 05:15:38 -07001023 case REC_TYPE_SECT:
1024 switch (fragType) {
1025 case INTERSECT_LINE:
1026 first = 1; last = 5; first2 = 8; last2 = 12;
1027 break;
1028 case INTERSECT_LINE_2:
1029 first = 1; last = 5; first2 = 11; last2 = 15;
1030 break;
1031 case INTERSECT_LINE_NO:
1032 first = 0; last = 4; first2 = 4; last2 = 8;
1033 break;
caryclark1049f122015-04-20 08:31:59 -07001034 case INTERSECT_CONIC_LINE:
1035 first = 1; last = 7; first2 = 11; last2 = 15;
1036 break;
caryclarkdac1d172014-06-17 05:15:38 -07001037 case INTERSECT_QUAD_LINE:
1038 first = 1; last = 7; first2 = 10; last2 = 14;
1039 break;
caryclark1049f122015-04-20 08:31:59 -07001040 case INTERSECT_CONIC_LINE_2:
1041 first = 1; last = 7; first2 = 14; last2 = 18;
1042 break;
caryclarkdac1d172014-06-17 05:15:38 -07001043 case INTERSECT_QUAD_LINE_2:
1044 first = 1; last = 7; first2 = 13; last2 = 17;
1045 break;
caryclark1049f122015-04-20 08:31:59 -07001046 case INTERSECT_CONIC_LINE_NO:
1047 first = 0; last = 6; first2 = 7; last2 = 11;
1048 break;
caryclarkdac1d172014-06-17 05:15:38 -07001049 case INTERSECT_QUAD_LINE_NO:
1050 first = 0; last = 6; first2 = 6; last2 = 10;
1051 break;
caryclark1049f122015-04-20 08:31:59 -07001052 case INTERSECT_CONIC:
1053 first = 1; last = 7; first2 = 11; last2 = 17;
1054 break;
caryclarkdac1d172014-06-17 05:15:38 -07001055 case INTERSECT_QUAD:
1056 first = 1; last = 7; first2 = 10; last2 = 16;
1057 break;
caryclark1049f122015-04-20 08:31:59 -07001058 case INTERSECT_CONIC_2:
1059 first = 1; last = 7; first2 = 14; last2 = 20;
1060 break;
caryclarkdac1d172014-06-17 05:15:38 -07001061 case INTERSECT_QUAD_2:
1062 first = 1; last = 7; first2 = 13; last2 = 19;
1063 break;
caryclark1049f122015-04-20 08:31:59 -07001064 case INTERSECT_CONIC_NO:
1065 first = 0; last = 6; first2 = 7; last2 = 13;
1066 break;
caryclarkdac1d172014-06-17 05:15:38 -07001067 case INTERSECT_QUAD_NO:
1068 first = 0; last = 6; first2 = 6; last2 = 12;
1069 break;
1070 case INTERSECT_SELF_CUBIC:
1071 first = 1; last = 9;
1072 break;
1073 case INTERSECT_SELF_CUBIC_NO:
1074 first = 0; last = 8;
1075 break;
1076 case INTERSECT_CUBIC_LINE:
1077 first = 1; last = 9; first2 = 12; last2 = 16;
1078 break;
1079 case INTERSECT_CUBIC_LINE_2:
1080 first = 1; last = 9; first2 = 15; last2 = 19;
1081 break;
1082 case INTERSECT_CUBIC_LINE_3:
1083 first = 1; last = 9; first2 = 18; last2 = 22;
1084 break;
1085 case INTERSECT_CUBIC_LINE_NO:
1086 first = 0; last = 8; first2 = 8; last2 = 12;
1087 break;
1088 case INTERSECT_CUBIC_QUAD:
1089 first = 1; last = 9; first2 = 12; last2 = 18;
1090 break;
1091 case INTERSECT_CUBIC_QUAD_2:
1092 first = 1; last = 9; first2 = 15; last2 = 21;
1093 break;
1094 case INTERSECT_CUBIC_QUAD_3:
1095 first = 1; last = 9; first2 = 18; last2 = 24;
1096 break;
1097 case INTERSECT_CUBIC_QUAD_4:
1098 first = 1; last = 9; first2 = 21; last2 = 27;
1099 break;
1100 case INTERSECT_CUBIC_QUAD_NO:
1101 first = 0; last = 8; first2 = 8; last2 = 14;
1102 break;
1103 case INTERSECT_CUBIC:
1104 first = 1; last = 9; first2 = 12; last2 = 20;
1105 break;
1106 case INTERSECT_CUBIC_2:
1107 first = 1; last = 9; first2 = 15; last2 = 23;
1108 break;
1109 case INTERSECT_CUBIC_3:
1110 first = 1; last = 9; first2 = 18; last2 = 26;
1111 break;
1112 case INTERSECT_CUBIC_4:
1113 first = 1; last = 9; first2 = 21; last2 = 29;
1114 break;
1115 case INTERSECT_CUBIC_NO:
1116 first = 0; last = 8; first2 = 8; last2 = 16;
1117 break;
1118 default:
1119 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1120 throw "stop execution";
1121 }
1122 break;
1123 default:
1124 continue;
1125 }
1126 for (var idx = first; idx < last; idx += 2) {
1127 xmin = Math.min(xmin, frags[idx]);
1128 xmax = Math.max(xmax, frags[idx]);
1129 ymin = Math.min(ymin, frags[idx + 1]);
1130 ymax = Math.max(ymax, frags[idx + 1]);
1131 }
1132 for (var idx = first2; idx < last2; idx += 2) {
1133 xmin = Math.min(xmin, frags[idx]);
1134 xmax = Math.max(xmax, frags[idx]);
1135 ymin = Math.min(ymin, frags[idx + 1]);
1136 ymax = Math.max(ymax, frags[idx + 1]);
1137 }
1138 }
1139 }
1140 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1141 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1142 var recType = test[tIndex];
1143 var records = test[tIndex + 2];
1144 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1145 var fragType = records[recordIndex];
1146 var frags = records[recordIndex + 1];
1147 switch (recType) {
1148 case REC_TYPE_ACTIVE_OP:
1149 if (!draw_op) {
1150 break;
1151 }
1152 {
1153 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1154 curve_extremes(curve, angleBounds);
1155 }
1156 break;
1157 case REC_TYPE_ANGLE:
1158 if (!draw_angle) {
1159 break;
1160 }
caryclark54359292015-03-26 07:52:43 -07001161 {
caryclarkdac1d172014-06-17 05:15:38 -07001162 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1163 curve_extremes(curve, angleBounds);
1164 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1165 curve_extremes(curve, angleBounds);
1166 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1167 }
1168 break;
1169 case REC_TYPE_SORT:
1170 if (!draw_sort) {
1171 break;
1172 }
1173 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1174 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1175 curve_extremes(curve, angleBounds);
1176 }
1177 break;
1178 }
1179 }
1180 }
1181 xmin = Math.min(xmin, angleBounds[0]);
1182 ymin = Math.min(ymin, angleBounds[1]);
1183 xmax = Math.max(xmax, angleBounds[2]);
1184 ymax = Math.max(ymax, angleBounds[3]);
1185 setScale(xmin, xmax, ymin, ymax);
1186 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001187 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001188 }
1189 if (hasPath == true && hasComputedPath == false && draw_computed) {
1190 draw_computed = 0;
1191 }
1192}
1193
1194function curveByID(test, id) {
caryclark54359292015-03-26 07:52:43 -07001195 var tIndex = -3;
1196 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001197 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001198 if (recType == REC_TYPE_OP) {
1199 continue;
1200 }
1201 if (recType != REC_TYPE_PATH) {
caryclarkdac1d172014-06-17 05:15:38 -07001202 return [];
1203 }
1204 var records = test[tIndex + 2];
1205 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1206 var fragType = records[recordIndex];
1207 var frags = records[recordIndex + 1];
1208 if (frags[0] == id) {
1209 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001210 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001211 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001212 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001213 return [frags[1], frags[2], frags[3], frags[4],
1214 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001215 case PATH_CONIC:
1216 return [frags[1], frags[2], frags[3], frags[4],
1217 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001218 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001219 return [frags[1], frags[2], frags[3], frags[4],
1220 frags[5], frags[6], frags[7], frags[8]];
1221 }
1222 }
1223 }
caryclarkdac1d172014-06-17 05:15:38 -07001224 }
1225 return [];
1226}
1227
1228function curvePartialByID(test, id, t0, t1) {
caryclark54359292015-03-26 07:52:43 -07001229 var tIndex = -3;
1230 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001231 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001232 if (recType == REC_TYPE_OP) {
1233 continue;
1234 }
1235 if (recType != REC_TYPE_PATH) {
caryclarkdac1d172014-06-17 05:15:38 -07001236 return [];
1237 }
1238 var records = test[tIndex + 2];
1239 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1240 var fragType = records[recordIndex];
1241 var frags = records[recordIndex + 1];
1242 if (frags[0] == id) {
1243 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001244 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001245 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001246 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001247 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1248 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001249 case PATH_CONIC:
1250 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1251 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001252 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001253 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1254 frags[5], frags[6], frags[7], frags[8], t0, t1);
1255 }
1256 }
1257 }
caryclarkdac1d172014-06-17 05:15:38 -07001258 }
1259 return [];
1260}
1261
1262function idByCurve(test, frag, type) {
caryclark54359292015-03-26 07:52:43 -07001263 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001264 while (tIndex < test.length) {
1265 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001266 if (recType != REC_TYPE_PATH) {
1267 ++tIndex;
1268 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001269 }
1270 var records = test[tIndex + 2];
1271 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1272 var fragType = records[recordIndex];
1273 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001274 if (frag.length != frags.length - 1) {
1275 continue;
1276 }
caryclarkdac1d172014-06-17 05:15:38 -07001277 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001278 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001279 if (frag[0] != frags[1] || frag[1] != frags[2]
1280 || frag[2] != frags[3] || frag[3] != frags[4]) {
1281 continue;
1282 }
1283 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001284 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001285 if (frag[0] != frags[1] || frag[1] != frags[2]
1286 || frag[2] != frags[3] || frag[3] != frags[4]
1287 || frag[4] != frags[5] || frag[5] != frags[6]) {
1288 continue;
1289 }
1290 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001291 case PATH_CONIC:
1292 if (frag[0] != frags[1] || frag[1] != frags[2]
1293 || frag[2] != frags[3] || frag[3] != frags[4]
1294 || frag[4] != frags[5] || frag[5] != frags[6]
1295 || frag[6] != frags[7]) {
1296 continue;
1297 }
1298 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001299 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001300 if (frag[0] != frags[1] || frag[1] != frags[2]
1301 || frag[2] != frags[3] || frag[3] != frags[4]
1302 || frag[4] != frags[5] || frag[5] != frags[6]
1303 || frag[6] != frags[7] || frag[7] != frags[8]) {
1304 continue;
1305 }
1306 return frags[0];
1307 }
1308 }
1309 ++tIndex;
1310 }
1311 return -1;
1312}
1313
1314function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001315 var length = curve.length == 7 ? 6 : curve.length;
caryclarkdac1d172014-06-17 05:15:38 -07001316 for (var index = 0; index < curve.length; index += 2) {
1317 var x = curve[index];
1318 var y = curve[index + 1];
1319 bounds[0] = Math.min(bounds[0], x);
1320 bounds[1] = Math.min(bounds[1], y);
1321 bounds[2] = Math.max(bounds[2], x);
1322 bounds[3] = Math.max(bounds[3], y);
1323 }
1324}
1325
1326function setScale(x0, x1, y0, y1) {
1327 var srcWidth = x1 - x0;
1328 var srcHeight = y1 - y0;
1329 var usableWidth = screenWidth;
1330 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1331 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1332 usableWidth -= (xDigits + yDigits) * 10;
1333 usableWidth -= decimal_places * 10;
1334 if (draw_legend) {
1335 usableWidth -= 40;
1336 }
1337 var hscale = usableWidth / srcWidth;
1338 var vscale = screenHeight / srcHeight;
1339 scale = Math.min(hscale, vscale);
1340 var invScale = 1 / scale;
1341 var sxmin = x0 - invScale * 5;
1342 var symin = y0 - invScale * 10;
1343 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1344 var symax = y1 + invScale * 10;
1345 srcWidth = sxmax - sxmin;
1346 srcHeight = symax - symin;
1347 hscale = usableWidth / srcWidth;
1348 vscale = screenHeight / srcHeight;
1349 scale = Math.min(hscale, vscale);
1350 srcLeft = sxmin;
1351 srcTop = symin;
1352}
1353
1354function drawArc(curve, op, from, to) {
1355 var type = PATH_LINE + (curve.length / 2 - 2);
1356 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1357 var dy = pt.y - curve[1];
1358 var dx = pt.x - curve[0];
1359 var dist = Math.sqrt(dy * dy + dx * dx);
1360 var _dist = dist * scale;
1361 var angle = Math.atan2(dy, dx);
1362 var _px = (curve[0] - srcLeft) * scale;
1363 var _py = (curve[1] - srcTop) * scale;
1364 var divisor = 4;
1365 var endDist;
1366 do {
1367 var ends = [];
1368 for (var index = -1; index <= 1; index += 2) {
1369 var px = Math.cos(index * Math.PI / divisor);
1370 var py = Math.sin(index * Math.PI / divisor);
1371 ends.push(px);
1372 ends.push(py);
1373 }
1374 var endDx = (ends[2] - ends[0]) * scale * dist;
1375 var endDy = (ends[3] - ends[1]) * scale * dist;
1376 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1377 if (endDist < 100) {
1378 break;
1379 }
1380 divisor *= 2;
1381 } while (true);
1382 if (endDist < 30) {
1383 return;
1384 }
1385 if (op) {
1386 divisor *= 2;
1387 }
1388 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1389 ctx.beginPath();
1390 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1391 ctx.stroke();
1392 var saveAlign = ctx.textAlign;
1393 var saveStyle = ctx.fillStyle;
1394 var saveFont = ctx.font;
1395 ctx.textAlign = "center";
1396 ctx.fillStyle = "black";
1397 ctx.font = "normal 24px Arial";
1398 divisor *= 0.8;
1399 for (var index = -1; index <= 1; index += 2) {
1400 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1401 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1402 var _px = (px - srcLeft) * scale;
1403 var _py = (py - srcTop) * scale;
1404 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1405 }
1406 ctx.textAlign = saveAlign;
1407 ctx.fillStyle = saveStyle;
1408 ctx.font = saveFont;
1409}
1410
1411function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001412 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1413 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001414 var x = drawnPts[pts];
1415 var y = drawnPts[pts + 1];
1416 if (px == x && py == y) {
1417 return;
1418 }
1419 }
1420 drawnPts.push(px);
1421 drawnPts.push(py);
1422 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1423 var _px = (px - srcLeft) * scale;
1424 var _py = (py - srcTop) * scale;
1425 ctx.beginPath();
1426 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1427 ctx.closePath();
1428 if (end) {
1429 ctx.fill();
1430 } else {
1431 ctx.stroke();
1432 }
1433 if (debug_xy) {
1434 ctx.textAlign = "left";
1435 ctx.fillText(label, _px + 5, _py);
1436 }
1437}
1438
caryclark1049f122015-04-20 08:31:59 -07001439function coordCount(curveType) {
1440 switch (curveType) {
1441 case PATH_LINE:
1442 return 4;
1443 case PATH_QUAD:
1444 return 6;
1445 case PATH_CONIC:
1446 return 6;
1447 case PATH_CUBIC:
1448 return 8;
1449 }
1450 return -1;
1451}
1452
caryclarkdac1d172014-06-17 05:15:38 -07001453function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001454 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001455 for (var idx = 0; idx < count; idx += 2) {
1456 if (!drawControls && idx != 0 && idx != count - 2) {
1457 continue;
1458 }
1459 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1460 }
1461}
1462
1463function drawControlLines(curve, curveType, drawEnd) {
1464 if (curveType == PATH_LINE) {
1465 return;
1466 }
1467 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1468 drawLine(curve[0], curve[1], curve[2], curve[3]);
1469 drawLine(curve[2], curve[3], curve[4], curve[5]);
1470 if (curveType == PATH_CUBIC) {
1471 drawLine(curve[4], curve[5], curve[6], curve[7]);
1472 if (drawEnd > 1) {
1473 drawLine(curve[6], curve[7], curve[0], curve[1]);
1474 if (drawEnd > 2) {
1475 drawLine(curve[0], curve[1], curve[4], curve[5]);
1476 drawLine(curve[6], curve[7], curve[2], curve[3]);
1477 }
1478 }
1479 } else if (drawEnd > 1) {
1480 drawLine(curve[4], curve[5], curve[0], curve[1]);
1481 }
1482}
1483
1484function pointAtT(curve, curveType, t) {
1485 var xy = {};
1486 switch (curveType) {
1487 case PATH_LINE:
1488 var a = 1 - t;
1489 var b = t;
1490 xy.x = a * curve[0] + b * curve[2];
1491 xy.y = a * curve[1] + b * curve[3];
1492 break;
1493 case PATH_QUAD:
1494 var one_t = 1 - t;
1495 var a = one_t * one_t;
1496 var b = 2 * one_t * t;
1497 var c = t * t;
1498 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1499 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1500 break;
caryclark1049f122015-04-20 08:31:59 -07001501 case PATH_CONIC:
1502 var one_t = 1 - t;
1503 var a = one_t * one_t;
1504 var b = 2 * one_t * t;
1505 var c = t * t;
1506 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1507 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1508 var d = a + b * curve[6] + c;
1509 xy.x /= d;
1510 xy.y /= d;
1511 break;
caryclarkdac1d172014-06-17 05:15:38 -07001512 case PATH_CUBIC:
1513 var one_t = 1 - t;
1514 var one_t2 = one_t * one_t;
1515 var a = one_t2 * one_t;
1516 var b = 3 * one_t2 * t;
1517 var t2 = t * t;
1518 var c = 3 * one_t * t2;
1519 var d = t2 * t;
1520 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1521 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1522 break;
1523 }
1524 return xy;
1525}
1526
1527function drawPointAtT(curve, curveType) {
1528 var x, y;
1529 var xy = pointAtT(curve, curveType, curveT);
1530 drawPoint(xy.x, xy.y, true);
1531 if (!draw_intersectT) {
1532 return;
1533 }
1534 ctx.fillStyle = "red";
1535 drawTAtPointUp(xy.x, xy.y, curveT);
1536}
1537
1538function drawTAtPointUp(px, py, t) {
1539 var label = t.toFixed(decimal_places);
1540 var _px = (px - srcLeft)* scale;
1541 var _py = (py - srcTop) * scale;
1542 ctx.fillText(label, _px + 5, _py - 10);
1543}
1544
1545function drawTAtPointDown(px, py, t) {
1546 var label = t.toFixed(decimal_places);
1547 var _px = (px - srcLeft)* scale;
1548 var _py = (py - srcTop) * scale;
1549 ctx.fillText(label, _px + 5, _py + 10);
1550}
1551
1552function alreadyDrawnLine(x1, y1, x2, y2) {
1553 if (collect_bounds) {
1554 if (focus_enabled) {
1555 focusXmin = Math.min(focusXmin, x1, x2);
1556 focusYmin = Math.min(focusYmin, y1, y2);
1557 focusXmax = Math.max(focusXmax, x1, x2);
1558 focusYmax = Math.max(focusYmax, y1, y2);
1559 }
1560 return true;
1561 }
1562 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1563 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1564 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1565 return true;
1566 }
1567 }
1568 drawnLines.push(x1);
1569 drawnLines.push(y1);
1570 drawnLines.push(x2);
1571 drawnLines.push(y2);
1572 return false;
1573}
1574
1575function drawLine(x1, y1, x2, y2) {
1576 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1577 return;
1578 }
1579 ctx.beginPath();
1580 ctx.moveTo((x1 - srcLeft) * scale,
1581 (y1 - srcTop) * scale);
1582 ctx.lineTo((x2 - srcLeft) * scale,
1583 (y2 - srcTop) * scale);
1584 ctx.stroke();
1585}
1586
1587function linePartial(x1, y1, x2, y2, t1, t2) {
1588 var dx = x1 - x2;
1589 var dy = y1 - y2;
1590 var array = [
1591 x1 - t1 * dx,
1592 y1 - t1 * dy,
1593 x1 - t2 * dx,
1594 y1 - t2 * dy
1595 ];
1596 return array;
1597}
1598
1599function drawLinePartial(x1, y1, x2, y2, t1, t2) {
1600 var a = linePartial(x1, y1, x2, y2, t1, t2);
1601 var ax = a[0];
1602 var ay = a[1];
1603 var bx = a[2];
1604 var by = a[3];
1605 if (alreadyDrawnLine(ax, ay, bx, by)) {
1606 return;
1607 }
1608 ctx.beginPath();
1609 ctx.moveTo((ax - srcLeft) * scale,
1610 (ay - srcTop) * scale);
1611 ctx.lineTo((bx - srcLeft) * scale,
1612 (by - srcTop) * scale);
1613 ctx.stroke();
1614}
1615
1616function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
1617 if (collect_bounds) {
1618 if (focus_enabled) {
1619 focusXmin = Math.min(focusXmin, x1, x2, x3);
1620 focusYmin = Math.min(focusYmin, y1, y2, y3);
1621 focusXmax = Math.max(focusXmax, x1, x2, x3);
1622 focusYmax = Math.max(focusYmax, y1, y2, y3);
1623 }
1624 return true;
1625 }
1626 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
1627 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
1628 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
1629 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
1630 return true;
1631 }
1632 }
1633 drawnQuads.push(x1);
1634 drawnQuads.push(y1);
1635 drawnQuads.push(x2);
1636 drawnQuads.push(y2);
1637 drawnQuads.push(x3);
1638 drawnQuads.push(y3);
1639 return false;
1640}
1641
1642function drawQuad(x1, y1, x2, y2, x3, y3) {
1643 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
1644 return;
1645 }
1646 ctx.beginPath();
1647 ctx.moveTo((x1 - srcLeft) * scale,
1648 (y1 - srcTop) * scale);
1649 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
1650 (y2 - srcTop) * scale,
1651 (x3 - srcLeft) * scale,
1652 (y3 - srcTop) * scale);
1653 ctx.stroke();
1654}
1655
1656function interp(A, B, t) {
1657 return A + (B - A) * t;
1658}
1659
1660function interp_quad_coords(x1, x2, x3, t)
1661{
1662 var ab = interp(x1, x2, t);
1663 var bc = interp(x2, x3, t);
1664 var abc = interp(ab, bc, t);
1665 return abc;
1666}
1667
1668function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1669 var ax = interp_quad_coords(x1, x2, x3, t1);
1670 var ay = interp_quad_coords(y1, y2, y3, t1);
1671 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
1672 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
1673 var cx = interp_quad_coords(x1, x2, x3, t2);
1674 var cy = interp_quad_coords(y1, y2, y3, t2);
1675 var bx = 2*dx - (ax + cx)/2;
1676 var by = 2*dy - (ay + cy)/2;
1677 var array = [
1678 ax, ay, bx, by, cx, cy
1679 ];
1680 return array;
1681}
1682
1683function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1684 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
1685 var ax = a[0];
1686 var ay = a[1];
1687 var bx = a[2];
1688 var by = a[3];
1689 var cx = a[4];
1690 var cy = a[5];
1691 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
1692 return;
1693 }
1694 ctx.beginPath();
1695 ctx.moveTo((ax - srcLeft) * scale,
1696 (ay - srcTop) * scale);
1697 ctx.quadraticCurveTo((bx - srcLeft) * scale,
1698 (by - srcTop) * scale,
1699 (cx - srcLeft) * scale,
1700 (cy - srcTop) * scale);
1701 ctx.stroke();
1702}
1703
caryclark1049f122015-04-20 08:31:59 -07001704function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
1705 if (collect_bounds) {
1706 if (focus_enabled) {
1707 focusXmin = Math.min(focusXmin, x1, x2, x3);
1708 focusYmin = Math.min(focusYmin, y1, y2, y3);
1709 focusXmax = Math.max(focusXmax, x1, x2, x3);
1710 focusYmax = Math.max(focusYmax, y1, y2, y3);
1711 }
1712 return true;
1713 }
1714 for (var pts = 0; pts < drawnConics.length; pts += 8) {
1715 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
1716 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1717 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1718 && w == drawnCubics[pts + 6]) {
1719 return true;
1720 }
1721 }
1722 drawnConics.push(x1);
1723 drawnConics.push(y1);
1724 drawnConics.push(x2);
1725 drawnConics.push(y2);
1726 drawnConics.push(x3);
1727 drawnConics.push(y3);
1728 drawnCubics.push(w);
1729 return false;
1730}
1731
1732var kMaxConicToQuadPOW2 = 5;
1733
1734function computeQuadPOW2(curve, tol) {
1735 var a = curve[6] - 1;
1736 var k = a / (4 * (2 + a));
1737 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
1738 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
1739
1740 var error = Math.sqrt(x * x + y * y);
1741 var pow2;
1742 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
1743 if (error <= tol) {
1744 break;
1745 }
1746 error *= 0.25;
1747 }
1748 return pow2;
1749}
1750
1751function subdivide_w_value(w) {
1752 return Math.sqrt(0.5 + w * 0.5);
1753}
1754
1755function chop(curve, part1, part2) {
1756 var w = curve[6];
1757 var scale = 1 / (1 + w);
1758 part1[0] = curve[0];
1759 part1[1] = curve[1];
1760 part1[2] = (curve[0] + curve[2] * w) * scale;
1761 part1[3] = (curve[1] + curve[3] * w) * scale;
1762 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
1763 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
1764 part2[2] = (curve[2] * w + curve[4]) * scale;
1765 part2[3] = (curve[3] * w + curve[5]) * scale;
1766 part2[4] = curve[4];
1767 part2[5] = curve[5];
1768 part1[6] = part2[6] = subdivide_w_value(w);
1769}
1770
1771function subdivide(curve, level, pts) {
1772 if (0 == level) {
1773 pts.push(curve[2]);
1774 pts.push(curve[3]);
1775 pts.push(curve[4]);
1776 pts.push(curve[5]);
1777 } else {
1778 var part1 = [], part2 = [];
1779 chop(curve, part1, part2);
1780 --level;
1781 subdivide(part1, level, pts);
1782 subdivide(part2, level, pts);
1783 }
1784}
1785
1786function chopIntoQuadsPOW2(curve, pow2, pts) {
1787 subdivide(curve, pow2, pts);
1788 return 1 << pow2;
1789}
1790
1791function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
1792 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
1793 return;
1794 }
1795 ctx.beginPath();
1796 ctx.moveTo((x1 - srcLeft) * scale,
1797 (y1 - srcTop) * scale);
1798 var tol = 1 / scale;
1799 var curve = [x1, y1, x2, y2, x3, y3, w];
1800 var pow2 = computeQuadPOW2(curve, tol);
1801 var pts = [];
1802 chopIntoQuadsPOW2(curve, pow2, pts);
1803 for (var i = 0; i < pts.length; i += 4) {
1804 ctx.quadraticCurveTo(
1805 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
1806 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
1807 }
1808 ctx.stroke();
1809}
1810
1811function conic_eval_numerator(x1, x2, x3, w, t) {
1812 var src2w = x2 * w;
1813 var C = x1;
1814 var A = x3 - 2 * src2w + C;
1815 var B = 2 * (src2w - C);
1816 return (A * t + B) * t + C;
1817}
1818
1819
1820function conic_eval_denominator(w, t) {
1821 var B = 2 * (w - 1);
1822 var C = 1;
1823 var A = -B;
1824 return (A * t + B) * t + C;
1825}
1826
1827function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
1828 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
1829 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
1830 var az = conic_eval_denominator(w, t1);
1831 var midT = (t1 + t2) / 2;
1832 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
1833 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
1834 var dz = conic_eval_denominator(w, midT);
1835 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
1836 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
1837 var cz = conic_eval_denominator(w, t2);
1838 var bx = 2 * dx - (ax + cx) / 2;
1839 var by = 2 * dy - (ay + cy) / 2;
1840 var bz = 2 * dz - (az + cz) / 2;
1841 var dt = t2 - t1;
1842 var dt_1 = 1 - dt;
1843 var partW = (1 + dt * (w - 1)) / Math.sqrt(dt * dt + 2 * dt * dt_1 * w + dt_1 * dt_1);
1844 var array = [
1845 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, partW
1846 ];
1847 return array;
1848}
1849
1850function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
1851 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
1852 var ax = a[0];
1853 var ay = a[1];
1854 var bx = a[2];
1855 var by = a[3];
1856 var cx = a[4];
1857 var cy = a[5];
1858 var w_ = a[6];
1859 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
1860}
1861
caryclarkdac1d172014-06-17 05:15:38 -07001862function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
1863 if (collect_bounds) {
1864 if (focus_enabled) {
1865 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
1866 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
1867 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
1868 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
1869 }
1870 return true;
1871 }
1872 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
1873 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
1874 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1875 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1876 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
1877 return true;
1878 }
1879 }
1880 drawnCubics.push(x1);
1881 drawnCubics.push(y1);
1882 drawnCubics.push(x2);
1883 drawnCubics.push(y2);
1884 drawnCubics.push(x3);
1885 drawnCubics.push(y3);
1886 drawnCubics.push(x4);
1887 drawnCubics.push(y4);
1888 return false;
1889}
1890
1891function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
1892 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
1893 return;
1894 }
1895 ctx.beginPath();
1896 ctx.moveTo((x1 - srcLeft) * scale,
1897 (y1 - srcTop) * scale);
1898 ctx.bezierCurveTo((x2 - srcLeft) * scale,
1899 (y2 - srcTop) * scale,
1900 (x3 - srcLeft) * scale,
1901 (y3 - srcTop) * scale,
1902 (x4 - srcLeft) * scale,
1903 (y4 - srcTop) * scale);
1904 ctx.stroke();
1905}
1906
1907function interp_cubic_coords(x1, x2, x3, x4, t)
1908{
1909 var ab = interp(x1, x2, t);
1910 var bc = interp(x2, x3, t);
1911 var cd = interp(x3, x4, t);
1912 var abc = interp(ab, bc, t);
1913 var bcd = interp(bc, cd, t);
1914 var abcd = interp(abc, bcd, t);
1915 return abcd;
1916}
1917
1918function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
1919 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
1920 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
1921 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
1922 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
1923 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
1924 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
1925 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
1926 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
1927 var mx = ex * 27 - ax * 8 - dx;
1928 var my = ey * 27 - ay * 8 - dy;
1929 var nx = fx * 27 - ax - dx * 8;
1930 var ny = fy * 27 - ay - dy * 8;
1931 var bx = (mx * 2 - nx) / 18;
1932 var by = (my * 2 - ny) / 18;
1933 var cx = (nx * 2 - mx) / 18;
1934 var cy = (ny * 2 - my) / 18;
1935 var array = [
1936 ax, ay, bx, by, cx, cy, dx, dy
1937 ];
1938 return array;
1939}
1940
1941function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
1942 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
1943 var ax = a[0];
1944 var ay = a[1];
1945 var bx = a[2];
1946 var by = a[3];
1947 var cx = a[4];
1948 var cy = a[5];
1949 var dx = a[6];
1950 var dy = a[7];
1951 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
1952 return;
1953 }
1954 ctx.beginPath();
1955 ctx.moveTo((ax - srcLeft) * scale,
1956 (ay - srcTop) * scale);
1957 ctx.bezierCurveTo((bx - srcLeft) * scale,
1958 (by - srcTop) * scale,
1959 (cx - srcLeft) * scale,
1960 (cy - srcTop) * scale,
1961 (dx - srcLeft) * scale,
1962 (dy - srcTop) * scale);
1963 ctx.stroke();
1964}
1965
1966function drawCurve(c) {
1967 switch (c.length) {
1968 case 4:
1969 drawLine(c[0], c[1], c[2], c[3]);
1970 break;
1971 case 6:
1972 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
1973 break;
caryclark1049f122015-04-20 08:31:59 -07001974 case 7:
1975 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
1976 break;
caryclarkdac1d172014-06-17 05:15:38 -07001977 case 8:
1978 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
1979 break;
1980 }
1981}
1982
1983function boundsWidth(pts) {
1984 var min = pts[0];
1985 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07001986 var length = pts.length == 7 ? 6 : pts.length;
1987 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001988 min = Math.min(min, pts[idx]);
1989 max = Math.max(max, pts[idx]);
1990 }
1991 return max - min;
1992}
1993
1994function boundsHeight(pts) {
1995 var min = pts[1];
1996 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07001997 var length = pts.length == 7 ? 6 : pts.length;
1998 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001999 min = Math.min(min, pts[idx]);
2000 max = Math.max(max, pts[idx]);
2001 }
2002 return max - min;
2003}
2004
2005function tangent(pts) {
2006 var dx = pts[2] - pts[0];
2007 var dy = pts[3] - pts[1];
2008 if (dx == 0 && dy == 0 && pts.length > 4) {
2009 dx = pts[4] - pts[0];
2010 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002011 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002012 dx = pts[6] - pts[0];
2013 dy = pts[7] - pts[1];
2014 }
2015 }
2016 return Math.atan2(-dy, dx);
2017}
2018
2019function hodograph(cubic) {
2020 var hodo = [];
2021 hodo[0] = 3 * (cubic[2] - cubic[0]);
2022 hodo[1] = 3 * (cubic[3] - cubic[1]);
2023 hodo[2] = 3 * (cubic[4] - cubic[2]);
2024 hodo[3] = 3 * (cubic[5] - cubic[3]);
2025 hodo[4] = 3 * (cubic[6] - cubic[4]);
2026 hodo[5] = 3 * (cubic[7] - cubic[5]);
2027 return hodo;
2028}
2029
2030function hodograph2(cubic) {
2031 var quad = hodograph(cubic);
2032 var hodo = [];
2033 hodo[0] = 2 * (quad[2] - quad[0]);
2034 hodo[1] = 2 * (quad[3] - quad[1]);
2035 hodo[2] = 2 * (quad[4] - quad[2]);
2036 hodo[3] = 2 * (quad[5] - quad[3]);
2037 return hodo;
2038}
2039
2040function quadraticRootsReal(A, B, C, s) {
2041 if (A == 0) {
2042 if (B == 0) {
2043 s[0] = 0;
2044 return C == 0;
2045 }
2046 s[0] = -C / B;
2047 return 1;
2048 }
2049 /* normal form: x^2 + px + q = 0 */
2050 var p = B / (2 * A);
2051 var q = C / A;
2052 var p2 = p * p;
2053 if (p2 < q) {
2054 return 0;
2055 }
2056 var sqrt_D = 0;
2057 if (p2 > q) {
2058 sqrt_D = sqrt(p2 - q);
2059 }
2060 s[0] = sqrt_D - p;
2061 s[1] = -sqrt_D - p;
2062 return 1 + s[0] != s[1];
2063}
2064
2065function add_valid_ts(s, realRoots, t) {
2066 var foundRoots = 0;
2067 for (var index = 0; index < realRoots; ++index) {
2068 var tValue = s[index];
2069 if (tValue >= 0 && tValue <= 1) {
2070 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2071 if (t[idx2] != tValue) {
2072 t[foundRoots++] = tValue;
2073 }
2074 }
2075 }
2076 }
2077 return foundRoots;
2078}
2079
2080function quadraticRootsValidT(a, b, c, t) {
2081 var s = [];
2082 var realRoots = quadraticRootsReal(A, B, C, s);
2083 var foundRoots = add_valid_ts(s, realRoots, t);
2084 return foundRoots != 0;
2085}
2086
2087function find_cubic_inflections(cubic, tValues) {
2088 var Ax = src[2] - src[0];
2089 var Ay = src[3] - src[1];
2090 var Bx = src[4] - 2 * src[2] + src[0];
2091 var By = src[5] - 2 * src[3] + src[1];
2092 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2093 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2094 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2095 Ax * By - Ay * Bx, tValues);
2096}
2097
2098function dxy_at_t(curve, type, t) {
2099 var dxy = {};
2100 if (type == PATH_QUAD) {
2101 var a = t - 1;
2102 var b = 1 - 2 * t;
2103 var c = t;
2104 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2105 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002106 } else if (type == PATH_CONIC) {
2107 var p20x = curve[4] - curve[0];
2108 var p20y = curve[5] - curve[1];
2109 var p10xw = (curve[2] - curve[0]) * curve[6];
2110 var p10yw = (curve[3] - curve[1]) * curve[6];
2111 var coeff0x = curve[6] * p20x - p20x;
2112 var coeff0y = curve[6] * p20y - p20y;
2113 var coeff1x = p20x - 2 * p10xw;
2114 var coeff1y = p20y - 2 * p10yw;
2115 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2116 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002117 } else if (type == PATH_CUBIC) {
2118 var one_t = 1 - t;
2119 var a = curve[0];
2120 var b = curve[2];
2121 var c = curve[4];
2122 var d = curve[6];
2123 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2124 a = curve[1];
2125 b = curve[3];
2126 c = curve[5];
2127 d = curve[7];
2128 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2129 }
2130 return dxy;
2131}
2132
2133function drawLabel(num, px, py) {
2134 ctx.beginPath();
2135 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2136 ctx.closePath();
2137 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2138 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2139 ctx.stroke();
2140 ctx.fillStyle = "black";
2141 ctx.font = "normal 10px Arial";
2142 // ctx.rotate(0.001);
2143 ctx.fillText(num, px - 2, py + 3);
2144 // ctx.rotate(-0.001);
2145}
2146
2147function drawLabelX(ymin, num, loc) {
2148 var px = (loc - srcLeft) * scale;
2149 var py = (ymin - srcTop) * scale - 20;
2150 drawLabel(num, px, py);
2151}
2152
2153function drawLabelY(xmin, num, loc) {
2154 var px = (xmin - srcLeft) * scale - 20;
2155 var py = (loc - srcTop) * scale;
2156 drawLabel(num, px, py);
2157}
2158
2159function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2160 ctx.beginPath();
2161 ctx.moveTo(hx, hy - 100);
2162 ctx.lineTo(hx, hy);
2163 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2164 ctx.stroke();
2165 ctx.beginPath();
2166 ctx.moveTo(hx, hy);
2167 ctx.lineTo(hx, hy + 100);
2168 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2169 ctx.stroke();
2170 ctx.beginPath();
2171 ctx.moveTo(hx - 100, hy);
2172 ctx.lineTo(hx, hy);
2173 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2174 ctx.stroke();
2175 ctx.beginPath();
2176 ctx.moveTo(hx, hy);
2177 ctx.lineTo(hx + 100, hy);
2178 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2179 ctx.stroke();
2180}
2181
2182function scalexy(x, y, mag) {
2183 var length = Math.sqrt(x * x + y * y);
2184 return mag / length;
2185}
2186
2187function drawArrow(x, y, dx, dy) {
2188 var dscale = scalexy(dx, dy, 1 / scale * 100);
2189 dx *= dscale;
2190 dy *= dscale;
2191 ctx.beginPath();
2192 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2193 x += dx;
2194 y += dy;
2195 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2196 dx /= 10;
2197 dy /= 10;
2198 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2199 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2200 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2201 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2202 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2203 ctx.stroke();
2204}
2205
2206function x_at_t(curve, t) {
2207 var one_t = 1 - t;
2208 if (curve.length == 4) {
2209 return one_t * curve[0] + t * curve[2];
2210 }
2211 var one_t2 = one_t * one_t;
2212 var t2 = t * t;
2213 if (curve.length == 6) {
2214 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2215 }
caryclark1049f122015-04-20 08:31:59 -07002216 if (curve.length == 7) {
2217 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2218 / (one_t2 +2 * one_t * t * curve[6] + t2);
2219 }
caryclarkdac1d172014-06-17 05:15:38 -07002220 var a = one_t2 * one_t;
2221 var b = 3 * one_t2 * t;
2222 var c = 3 * one_t * t2;
2223 var d = t2 * t;
2224 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2225}
2226
2227function y_at_t(curve, t) {
2228 var one_t = 1 - t;
2229 if (curve.length == 4) {
2230 return one_t * curve[1] + t * curve[3];
2231 }
2232 var one_t2 = one_t * one_t;
2233 var t2 = t * t;
2234 if (curve.length == 6) {
2235 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2236 }
caryclark1049f122015-04-20 08:31:59 -07002237 if (curve.length == 7) {
2238 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2239 / (one_t2 +2 * one_t * t * curve[6] + t2);
2240 }
caryclarkdac1d172014-06-17 05:15:38 -07002241 var a = one_t2 * one_t;
2242 var b = 3 * one_t2 * t;
2243 var c = 3 * one_t * t2;
2244 var d = t2 * t;
2245 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2246}
2247
2248function drawOrder(curve, label) {
2249 var px = x_at_t(curve, 0.75);
2250 var py = y_at_t(curve, 0.75);
2251 var _px = (px - srcLeft) * scale;
2252 var _py = (py - srcTop) * scale;
2253 ctx.beginPath();
2254 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2255 ctx.closePath();
2256 ctx.fillStyle = "white";
2257 ctx.fill();
2258 if (label == 'L') {
2259 ctx.strokeStyle = "rgba(255,0,0, 1)";
2260 ctx.fillStyle = "rgba(255,0,0, 1)";
2261 } else {
2262 ctx.strokeStyle = "rgba(0,0,255, 1)";
2263 ctx.fillStyle = "rgba(0,0,255, 1)";
2264 }
2265 ctx.stroke();
2266 ctx.font = "normal 16px Arial";
2267 ctx.textAlign = "center";
2268 ctx.fillText(label, _px, _py + 5);
2269 ctx.font = "normal 10px Arial";
2270}
2271
2272function drawID(curve, id) {
2273 var px = x_at_t(curve, 0.5);
2274 var py = y_at_t(curve, 0.5);
2275 var _px = (px - srcLeft) * scale;
2276 var _py = (py - srcTop) * scale;
2277 draw_id_at(id, _px, _py);
2278}
2279
2280function draw_id_at(id, _px, _py) {
2281 ctx.beginPath();
2282 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2283 ctx.closePath();
2284 ctx.fillStyle = "white";
2285 ctx.fill();
2286 ctx.strokeStyle = "rgba(127,127,0, 1)";
2287 ctx.fillStyle = "rgba(127,127,0, 1)";
2288 ctx.stroke();
2289 ctx.font = "normal 16px Arial";
2290 ctx.textAlign = "center";
2291 ctx.fillText(id, _px, _py + 5);
2292 ctx.font = "normal 10px Arial";
2293}
2294
2295function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2296 var curve = [x1, y1, x2, y2];
2297 drawCurvePartialID(id, curve, t1, t2);
2298}
2299
2300function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2301 var curve = [x1, y1, x2, y2, x3, y3];
2302 drawCurvePartialID(id, curve, t1, t2);
2303}
2304
caryclark1049f122015-04-20 08:31:59 -07002305function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2306 var curve = [x1, y1, x2, y2, x3, y3, w];
2307 drawCurvePartialID(id, curve, t1, t2);
2308}
2309
caryclarkdac1d172014-06-17 05:15:38 -07002310function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2311 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2312 drawCurvePartialID(id, curve, t1, t2);
2313}
2314
2315function drawCurvePartialID(id, curve, t1, t2) {
2316 var px = x_at_t(curve, (t1 + t2) / 2);
2317 var py = y_at_t(curve, (t1 + t2) / 2);
2318 var _px = (px - srcLeft) * scale;
2319 var _py = (py - srcTop) * scale;
2320 draw_id_at(id, _px, _py);
2321}
2322
2323function drawCurveSpecials(test, curve, type) {
2324 if (pt_labels) {
2325 drawPoints(curve, type, pt_labels == 2);
2326 }
2327 if (control_lines != 0) {
2328 drawControlLines(curve, type, control_lines);
2329 }
2330 if (curve_t) {
2331 drawPointAtT(curve, type);
2332 }
2333 if (draw_midpoint) {
2334 var mid = pointAtT(curve, type, 0.5);
2335 drawPoint(mid.x, mid.y, true);
2336 }
2337 if (draw_id) {
2338 var id = idByCurve(test, curve, type);
2339 if (id >= 0) {
2340 drawID(curve, id);
2341 }
2342 }
2343 if (type == PATH_LINE) {
2344 return;
2345 }
2346 if (draw_deriviatives > 0) {
2347 var d = dxy_at_t(curve, type, 0);
2348 drawArrow(curve[0], curve[1], d.x, d.y);
2349 if (draw_deriviatives == 2) {
2350 d = dxy_at_t(curve, type, 1);
2351 if (type == PATH_CUBIC) {
2352 drawArrow(curve[6], curve[7], d.x, d.y);
2353 } else {
2354 drawArrow(curve[4], curve[5], d.x, d.y);
2355 }
2356 }
2357 if (draw_midpoint) {
2358 var mid = pointAtT(curve, type, 0.5);
2359 d = dxy_at_t(curve, type, 0.5);
2360 drawArrow(mid.x, mid.y, d.x, d.y);
2361 }
2362 }
2363 if (type != PATH_CUBIC) {
2364 return;
2365 }
caryclarkdac1d172014-06-17 05:15:38 -07002366 if (draw_sequence) {
2367 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2368 for (var i = 0; i < 8; i+= 2) {
2369 drawLabelX(ymin, i >> 1, curve[i]);
2370 }
2371 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2372 for (var i = 1; i < 8; i+= 2) {
2373 drawLabelY(xmin, i >> 1, curve[i]);
2374 }
2375 }
2376}
2377
2378function logCurves(test) {
2379 for (curves in test) {
2380 var curve = test[curves];
2381 dumpCurve(curve);
2382 }
2383}
2384
2385function curveToString(curve) {
2386 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002387 var length = curve.length == 7 ? 6 : curve.length;
2388 if (curve.length == 7) {
2389 str += "{";
2390 }
2391 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002392 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2393 if (i < curve.length - 2) {
2394 str += "}, {";
2395 }
2396 }
caryclark1049f122015-04-20 08:31:59 -07002397 str += "}";
2398 if (curve.length == 7) {
2399 str += "}, " + curve[6].toFixed(decimal_places);
2400 }
2401 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07002402 return str;
2403}
2404
2405function dumpCurve(curve) {
2406 console.log(curveToString(curve));
2407}
2408
2409function draw(test, lines, title) {
2410 ctx.fillStyle = "rgba(0,0,0, 0.1)";
2411 ctx.font = "normal 50px Arial";
2412 ctx.textAlign = "left";
2413 ctx.fillText(title, 50, 50);
2414 ctx.font = "normal 10px Arial";
2415 ctx.lineWidth = "1.001"; "0.999";
2416 var secondPath = test.length;
2417 var closeCount = 0;
2418 logStart = -1;
2419 logRange = 0;
2420 // find last active rec type at this step
2421 var curType = test[0];
2422 var curStep = 0;
2423 var hasOp = false;
2424 var lastActive = 0;
2425 var lastAdd = 0;
2426 var lastSect = 0;
2427 var lastSort = 0;
2428 var lastMark = 0;
2429 activeCount = 0;
2430 addCount = 0;
2431 angleCount = 0;
2432 opCount = 0;
2433 sectCount = 0;
2434 sortCount = 0;
2435 markCount = 0;
2436 activeMax = 0;
2437 addMax = 0;
2438 angleMax = 0;
2439 opMax = 0;
2440 sectMax = 0;
2441 sectMax2 = 0;
2442 sortMax = 0;
2443 markMax = 0;
2444 lastIndex = test.length - 3;
2445 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
2446 var recType = test[tIndex];
2447 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
2448 console.log("unknown rec type: " + recType);
2449 throw "stop execution";
2450 }
2451 // if (curType == recType && curType != REC_TYPE_ADD) {
2452 // continue;
2453 // }
2454 var inStepRange = step_limit == 0 || curStep < step_limit;
2455 curType = recType;
2456 if (recType == REC_TYPE_OP) {
2457 hasOp = true;
2458 continue;
2459 }
2460 if (recType == REC_TYPE_UNKNOWN) {
2461 // these types do not advance step
2462 continue;
2463 }
2464 var bumpStep = false;
2465 var records = test[tIndex + 2];
2466 var fragType = records[0];
2467 if (recType == REC_TYPE_ADD) {
2468 if (records.length != 2) {
2469 console.log("expect only two elements: " + records.length);
2470 throw "stop execution";
2471 }
2472 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
2473 continue;
2474 }
2475 ++addMax;
2476 if (!draw_add || !inStepRange) {
2477 continue;
2478 }
2479 lastAdd = tIndex;
2480 ++addCount;
2481 bumpStep = true;
2482 }
2483 if (recType == REC_TYPE_PATH && hasOp) {
2484 secondPath = tIndex;
2485 }
caryclark54359292015-03-26 07:52:43 -07002486 if (recType == REC_TYPE_PATH2 && hasOp) {
2487 secondPath = tIndex;
2488 }
caryclarkdac1d172014-06-17 05:15:38 -07002489 if (recType == REC_TYPE_ACTIVE) {
2490 ++activeMax;
2491 if (!draw_active || !inStepRange) {
2492 continue;
2493 }
2494 lastActive = tIndex;
2495 ++activeCount;
2496 bumpStep = true;
2497 }
2498 if (recType == REC_TYPE_ACTIVE_OP) {
2499 ++opMax;
2500 if (!draw_op || !inStepRange) {
2501 continue;
2502 }
2503 lastOp = tIndex;
2504 ++opCount;
2505 bumpStep = true;
2506 }
caryclark54359292015-03-26 07:52:43 -07002507 if (recType == REC_TYPE_AFTERPART) {
2508 if (draw_angle != 3 || !inStepRange) {
2509 continue;
2510 }
2511 lastAngle = tIndex;
2512 ++angleCount;
2513 bumpStep = true;
2514 }
caryclarkdac1d172014-06-17 05:15:38 -07002515 if (recType == REC_TYPE_ANGLE) {
2516 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07002517 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07002518 continue;
2519 }
2520 lastAngle = tIndex;
2521 ++angleCount;
2522 bumpStep = true;
2523 }
2524 if (recType == REC_TYPE_SECT) {
2525 if (records.length != 2) {
2526 console.log("expect only two elements: " + records.length);
2527 throw "stop execution";
2528 }
2529 ++sectMax;
2530 var sectBump = 1;
2531 switch (fragType) {
2532 case INTERSECT_LINE:
2533 case INTERSECT_QUAD_LINE:
2534 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002535 case INTERSECT_CONIC_LINE:
2536 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07002537 case INTERSECT_SELF_CUBIC:
2538 case INTERSECT_CUBIC_LINE:
2539 case INTERSECT_CUBIC_QUAD:
2540 case INTERSECT_CUBIC:
2541 sectBump = 1;
2542 break;
2543 case INTERSECT_LINE_2:
2544 case INTERSECT_QUAD_LINE_2:
2545 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07002546 case INTERSECT_CONIC_LINE_2:
2547 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07002548 case INTERSECT_CUBIC_LINE_2:
2549 case INTERSECT_CUBIC_QUAD_2:
2550 case INTERSECT_CUBIC_2:
2551 sectBump = 2;
2552 break;
2553 case INTERSECT_LINE_NO:
2554 case INTERSECT_QUAD_LINE_NO:
2555 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07002556 case INTERSECT_CONIC_LINE_NO:
2557 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07002558 case INTERSECT_SELF_CUBIC_NO:
2559 case INTERSECT_CUBIC_LINE_NO:
2560 case INTERSECT_CUBIC_QUAD_NO:
2561 case INTERSECT_CUBIC_NO:
2562 sectBump = 0;
2563 break;
2564 case INTERSECT_CUBIC_LINE_3:
2565 case INTERSECT_CUBIC_QUAD_3:
2566 case INTERSECT_CUBIC_3:
2567 sectBump = 3;
2568 break;
2569 case INTERSECT_CUBIC_QUAD_4:
2570 case INTERSECT_CUBIC_4:
2571 sectBump = 4;
2572 break;
2573 default:
2574 console.log("missing case " + records.length);
2575 throw "stop execution";
2576 }
2577 sectMax2 += sectBump;
2578 if (draw_intersection <= 1 || !inStepRange) {
2579 continue;
2580 }
2581 lastSect = tIndex;
2582 sectCount += sectBump;
2583 bumpStep = true;
2584 }
2585 if (recType == REC_TYPE_SORT) {
2586 ++sortMax;
2587 if (!draw_sort || !inStepRange) {
2588 continue;
2589 }
2590 lastSort = tIndex;
2591 ++sortCount;
2592 bumpStep = true;
2593 }
2594 if (recType == REC_TYPE_MARK) {
2595 ++markMax;
2596 if (!draw_mark || !inStepRange) {
2597 continue;
2598 }
2599 lastMark = tIndex;
2600 ++markCount;
2601 bumpStep = true;
2602 }
2603 if (bumpStep) {
2604 lastIndex = tIndex;
2605 logStart = test[tIndex + 1];
2606 logRange = records.length / 2;
2607 ++curStep;
2608 }
2609 }
2610 stepMax = (draw_add ? addMax : 0)
2611 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07002612 + (draw_angle ? angleMax : 0)
caryclark54359292015-03-26 07:52:43 -07002613 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07002614 + (draw_sort ? sortMax : 0)
2615 + (draw_mark ? markMax : 0)
2616 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
2617 if (stepMax == 0) {
2618 stepMax = addMax + activeMax + angleMax + opMax + sortMax + markMax;
2619 }
2620 drawnPts = [];
2621 drawnLines = [];
2622 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07002623 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07002624 drawnCubics = [];
2625 focusXmin = focusYmin = Infinity;
2626 focusXmax = focusYmax = -Infinity;
2627 var pathIndex = 0;
2628 var opLetter = 'S';
2629 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
2630 var recType = test[tIndex];
2631 var records = test[tIndex + 2];
2632 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
2633 var fragType = records[recordIndex];
2634 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
2635 console.log("unknown in range frag type: " + fragType);
2636 throw "stop execution";
2637 }
2638 var frags = records[recordIndex + 1];
2639 focus_enabled = false;
2640 switch (recType) {
2641 case REC_TYPE_COMPUTED:
2642 if (draw_computed == 0) {
2643 continue;
2644 }
2645 ctx.lineWidth = 1;
2646 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
2647 ctx.fillStyle = "blue";
2648 var drawThis = false;
2649 switch (fragType) {
2650 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07002651 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
2652 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002653 drawQuad(frags[0], frags[1], frags[2], frags[3],
2654 frags[4], frags[5]);
2655 drawThis = true;
2656 }
2657 break;
caryclark1049f122015-04-20 08:31:59 -07002658 case PATH_CONIC:
2659 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
2660 && (draw_computed & 7) == pathIndex)) {
2661 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2662 frags[4], frags[5], frags[6]);
2663 drawThis = true;
2664 }
2665 break;
caryclarkdac1d172014-06-17 05:15:38 -07002666 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07002667 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
2668 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07002669 drawCubic(frags[0], frags[1], frags[2], frags[3],
2670 frags[4], frags[5], frags[6], frags[7]);
2671 drawThis = true;
2672 }
2673 ++pathIndex;
2674 break;
2675 case COMPUTED_SET_1:
2676 pathIndex = 0;
2677 break;
2678 case COMPUTED_SET_2:
2679 pathIndex = 1;
2680 break;
2681 default:
2682 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
2683 throw "stop execution";
2684 }
2685 if (!drawThis || collect_bounds) {
2686 break;
2687 }
2688 drawCurveSpecials(test, frags, fragType);
2689 break;
2690 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07002691 case REC_TYPE_PATH2:
caryclarkdac1d172014-06-17 05:15:38 -07002692 if (!draw_path) {
2693 continue;
2694 }
2695 var firstPath = tIndex < secondPath;
2696 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
2697 continue;
2698 }
2699 ctx.lineWidth = 1;
2700 ctx.strokeStyle = firstPath ? "black" : "red";
2701 ctx.fillStyle = "blue";
caryclark54359292015-03-26 07:52:43 -07002702 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07002703 switch (fragType) {
2704 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07002705 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
2706 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07002707 break;
2708 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07002709 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
2710 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
2711 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07002712 break;
caryclark1049f122015-04-20 08:31:59 -07002713 case PATH_CONIC:
2714 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
2715 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
2716 frags2[4], frags2[5], frags2[6]);
2717 break;
caryclarkdac1d172014-06-17 05:15:38 -07002718 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07002719 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
2720 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
2721 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07002722 break;
2723 default:
caryclark54359292015-03-26 07:52:43 -07002724 console.log("unknown REC_TYPE_PATH2 frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002725 throw "stop execution";
2726 }
2727 if (collect_bounds) {
2728 break;
2729 }
caryclark54359292015-03-26 07:52:43 -07002730 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07002731 break;
2732 case REC_TYPE_OP:
2733 switch (fragType) {
2734 case OP_INTERSECT: opLetter = 'I'; break;
2735 case OP_DIFFERENCE: opLetter = 'D'; break;
2736 case OP_UNION: opLetter = 'U'; break;
2737 case OP_XOR: opLetter = 'X'; break;
2738 default:
2739 console.log("unknown REC_TYPE_OP frag type: " + fragType);
2740 throw "stop execution";
2741 }
2742 break;
2743 case REC_TYPE_ACTIVE:
2744 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
2745 continue;
2746 }
2747 var x1 = frags[SPAN_X1];
2748 var y1 = frags[SPAN_Y1];
2749 var x2 = frags[SPAN_X2];
2750 var y2 = frags[SPAN_Y2];
caryclark1049f122015-04-20 08:31:59 -07002751 var x3, y3, x3, y4, t1, t2, w;
caryclarkdac1d172014-06-17 05:15:38 -07002752 ctx.lineWidth = 3;
2753 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2754 focus_enabled = true;
2755 switch (fragType) {
2756 case ACTIVE_LINE_SPAN:
2757 t1 = frags[SPAN_L_T];
2758 t2 = frags[SPAN_L_TEND];
2759 drawLinePartial(x1, y1, x2, y2, t1, t2);
2760 if (draw_id) {
2761 drawLinePartialID(frags[0], x1, y1, x2, y2, t1, t2);
2762 }
2763 break;
2764 case ACTIVE_QUAD_SPAN:
2765 x3 = frags[SPAN_X3];
2766 y3 = frags[SPAN_Y3];
2767 t1 = frags[SPAN_Q_T];
2768 t2 = frags[SPAN_Q_TEND];
2769 drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2770 if (draw_id) {
2771 drawQuadPartialID(frags[0], x1, y1, x2, y2, x3, y3, t1, t2);
2772 }
2773 break;
caryclark1049f122015-04-20 08:31:59 -07002774 case ACTIVE_CONIC_SPAN:
2775 x3 = frags[SPAN_X3];
2776 y3 = frags[SPAN_Y3];
2777 t1 = frags[SPAN_K_T];
2778 t2 = frags[SPAN_K_TEND];
2779 w = frags[SPAN_K_W];
2780 drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2781 if (draw_id) {
2782 drawConicPartialID(frags[0], x1, y1, x2, y2, x3, y3, w, t1, t2);
2783 }
2784 break;
caryclarkdac1d172014-06-17 05:15:38 -07002785 case ACTIVE_CUBIC_SPAN:
2786 x3 = frags[SPAN_X3];
2787 y3 = frags[SPAN_Y3];
2788 x4 = frags[SPAN_X4];
2789 y4 = frags[SPAN_Y4];
2790 t1 = frags[SPAN_C_T];
2791 t2 = frags[SPAN_C_TEND];
2792 drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2793 if (draw_id) {
2794 drawCubicPartialID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2795 }
2796 break;
2797 default:
2798 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
2799 throw "stop execution";
2800 }
2801 break;
2802 case REC_TYPE_ACTIVE_OP:
2803 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
2804 continue;
2805 }
2806 focus_enabled = true;
2807 ctx.lineWidth = 3;
2808 var activeSpan = frags[7] == "1";
2809 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
2810 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
2811 drawCurve(curve);
2812 if (draw_op > 1) {
2813 drawArc(curve, false, frags[3], frags[4]);
2814 drawArc(curve, true, frags[5], frags[6]);
2815 }
2816 break;
2817 case REC_TYPE_ADD:
2818 if (!draw_add) {
2819 continue;
2820 }
2821 ctx.lineWidth = 3;
2822 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
2823 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
2824 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
2825 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
2826 : "rgba(127,0,127, 0.3)";
2827 focus_enabled = true;
2828 switch (fragType) {
2829 case ADD_MOVETO:
2830 break;
2831 case ADD_LINETO:
2832 if (step_limit == 0 || tIndex >= lastAdd) {
2833 drawLine(frags[0], frags[1], frags[2], frags[3]);
2834 }
2835 break;
2836 case ADD_QUADTO:
2837 if (step_limit == 0 || tIndex >= lastAdd) {
2838 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
2839 }
2840 break;
caryclark1049f122015-04-20 08:31:59 -07002841 case ADD_CONICTO:
2842 if (step_limit == 0 || tIndex >= lastAdd) {
2843 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2844 frags[4], frags[5], frags[6]);
2845 }
2846 break;
caryclarkdac1d172014-06-17 05:15:38 -07002847 case ADD_CUBICTO:
2848 if (step_limit == 0 || tIndex >= lastAdd) {
2849 drawCubic(frags[0], frags[1], frags[2], frags[3],
2850 frags[4], frags[5], frags[6], frags[7]);
2851 }
2852 break;
2853 case ADD_CLOSE:
2854 ++closeCount;
2855 break;
2856 case ADD_FILL:
2857 break;
2858 default:
2859 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
2860 throw "stop execution";
2861 }
2862 break;
2863 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07002864 angleBetween = frags[18] == "T";
2865 afterIndex = 0;
2866 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07002867 continue;
2868 }
2869 focus_enabled = true;
2870 ctx.lineWidth = 3;
2871 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07002872 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
2873 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
2874 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07002875 drawCurve(leftCurve);
2876 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07002877 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07002878 drawCurve(midCurve);
2879 if (draw_angle > 1) {
2880 drawOrder(leftCurve, 'L');
2881 drawOrder(rightCurve, 'R');
2882 }
2883 break;
caryclark54359292015-03-26 07:52:43 -07002884 case REC_TYPE_AFTERPART:
2885 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
2886 continue;
2887 }
2888 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
2889 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
2890 : "rgba(0,0,255, 1.0)";
2891 switch (fragType) {
2892 case PATH_LINE:
2893 drawLine(frags[0], frags[1], frags[2], frags[3]);
2894 break;
2895 case PATH_QUAD:
2896 drawQuad(frags[0], frags[1], frags[2], frags[3],
2897 frags[4], frags[5]);
2898 break;
caryclark1049f122015-04-20 08:31:59 -07002899 case PATH_CONIC:
2900 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
2901 frags[4], frags[5], frags[6]);
2902 break;
caryclark54359292015-03-26 07:52:43 -07002903 case PATH_CUBIC:
2904 drawCubic(frags[0], frags[1], frags[2], frags[3],
caryclark1049f122015-04-20 08:31:59 -07002905 frags[4], frags[5], frags[6], frags[7]);
caryclark54359292015-03-26 07:52:43 -07002906 break;
2907 default:
2908 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
2909 throw "stop execution";
2910 }
2911 ++afterIndex;
2912 break;
caryclarkdac1d172014-06-17 05:15:38 -07002913 case REC_TYPE_SECT:
2914 if (!draw_intersection) {
2915 continue;
2916 }
2917 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
2918 continue;
2919 }
2920 // draw_intersection == 1 : show all
2921 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
2922 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
2923 ctx.lineWidth = 1;
2924 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2925 ctx.fillStyle = "blue";
2926 focus_enabled = true;
2927 var f = [];
2928 var c1s;
2929 var c1l;
2930 var c2s;
2931 var c2l;
2932 switch (fragType) {
2933 case INTERSECT_LINE:
2934 f.push(5, 6, 0, 7);
2935 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
2936 break;
2937 case INTERSECT_LINE_2:
2938 f.push(5, 6, 0, 10);
2939 f.push(8, 9, 7, 15);
2940 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
2941 break;
2942 case INTERSECT_LINE_NO:
2943 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
2944 break;
2945 case INTERSECT_QUAD_LINE:
2946 f.push(7, 8, 0, 9);
2947 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
2948 break;
2949 case INTERSECT_QUAD_LINE_2:
2950 f.push(7, 8, 0, 12);
2951 f.push(10, 11, 9, 17);
2952 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
2953 break;
2954 case INTERSECT_QUAD_LINE_NO:
2955 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
2956 break;
2957 case INTERSECT_QUAD:
2958 f.push(7, 8, 0, 9);
2959 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
2960 break;
2961 case INTERSECT_QUAD_2:
2962 f.push(7, 8, 0, 12);
2963 f.push(10, 11, 9, 19);
2964 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
2965 break;
2966 case INTERSECT_QUAD_NO:
2967 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
2968 break;
caryclark1049f122015-04-20 08:31:59 -07002969 case INTERSECT_CONIC_LINE:
2970 f.push(8, 9, 0, 10);
2971 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
2972 break;
2973 case INTERSECT_CONIC_LINE_2:
2974 f.push(8, 9, 0, 12);
2975 f.push(11, 12, 10, 18);
2976 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
2977 break;
2978 case INTERSECT_CONIC_LINE_NO:
2979 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
2980 break;
2981 case INTERSECT_CONIC:
2982 f.push(8, 9, 0, 10);
2983 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
2984 break;
2985 case INTERSECT_CONIC_2:
2986 f.push(8, 9, 0, 13);
2987 f.push(11, 12, 10, 21);
2988 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
2989 break;
2990 case INTERSECT_CONIC_NO:
2991 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
2992 break;
caryclarkdac1d172014-06-17 05:15:38 -07002993 case INTERSECT_SELF_CUBIC:
2994 f.push(9, 10, 0, 11);
2995 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
2996 break;
2997 case INTERSECT_SELF_CUBIC_NO:
2998 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
2999 break;
3000 case INTERSECT_CUBIC_LINE:
3001 f.push(9, 10, 0, 11);
3002 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3003 break;
3004 case INTERSECT_CUBIC_LINE_2:
3005 f.push(9, 10, 0, 14);
3006 f.push(12, 13, 11, 19);
3007 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3008 break;
3009 case INTERSECT_CUBIC_LINE_3:
3010 f.push(9, 10, 0, 17);
3011 f.push(12, 13, 11, 22);
3012 f.push(15, 16, 14, 23);
3013 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3014 break;
3015 case INTERSECT_CUBIC_QUAD_NO:
3016 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3017 break;
3018 case INTERSECT_CUBIC_QUAD:
3019 f.push(9, 10, 0, 11);
3020 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3021 break;
3022 case INTERSECT_CUBIC_QUAD_2:
3023 f.push(9, 10, 0, 14);
3024 f.push(12, 13, 11, 21);
3025 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3026 break;
3027 case INTERSECT_CUBIC_QUAD_3:
3028 f.push(9, 10, 0, 17);
3029 f.push(12, 13, 11, 24);
3030 f.push(15, 16, 14, 25);
3031 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3032 break;
3033 case INTERSECT_CUBIC_QUAD_4:
3034 f.push(9, 10, 0, 20);
3035 f.push(12, 13, 11, 27);
3036 f.push(15, 16, 14, 28);
3037 f.push(18, 19, 17, 29);
3038 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3039 break;
3040 case INTERSECT_CUBIC_LINE_NO:
3041 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3042 break;
3043 case INTERSECT_CUBIC:
3044 f.push(9, 10, 0, 11);
3045 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3046 break;
3047 case INTERSECT_CUBIC_2:
3048 f.push(9, 10, 0, 14);
3049 f.push(12, 13, 11, 23);
3050 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3051 break;
3052 case INTERSECT_CUBIC_3:
3053 f.push(9, 10, 0, 17);
3054 f.push(12, 13, 11, 26);
3055 f.push(15, 16, 14, 27);
3056 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3057 break;
3058 case INTERSECT_CUBIC_4:
3059 f.push(9, 10, 0, 20);
3060 f.push(12, 13, 11, 29);
3061 f.push(15, 16, 14, 30);
3062 f.push(18, 19, 17, 31);
3063 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3064 break;
3065 case INTERSECT_CUBIC_NO:
3066 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3067 break;
3068 default:
3069 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3070 throw "stop execution";
3071 }
3072 if (draw_intersection != 1) {
3073 var id = -1;
3074 var curve;
3075 switch (c1l) {
3076 case 4:
3077 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3078 if (draw_id) {
3079 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3080 id = idByCurve(test, curve, PATH_LINE);
3081 }
3082 break;
3083 case 6:
3084 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3085 frags[c1s + 4], frags[c1s + 5]);
3086 if (draw_id) {
3087 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3088 frags[c1s + 4], frags[c1s + 5]];
3089 id = idByCurve(test, curve, PATH_QUAD);
3090 }
3091 break;
caryclark1049f122015-04-20 08:31:59 -07003092 case 7:
3093 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3094 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3095 if (draw_id) {
3096 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3097 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3098 id = idByCurve(test, curve, PATH_CONIC);
3099 }
3100 break;
caryclarkdac1d172014-06-17 05:15:38 -07003101 case 8:
3102 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3103 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3104 if (draw_id) {
3105 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3106 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3107 id = idByCurve(test, curve, PATH_CUBIC);
3108 }
3109 break;
3110 }
3111 if (id >= 0) {
3112 drawID(curve, id);
3113 }
3114 id = -1;
3115 switch (c2l) {
3116 case 0:
3117 break;
3118 case 4:
3119 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3120 if (draw_id) {
3121 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3122 id = idByCurve(test, curve, PATH_LINE);
3123 }
3124 break;
3125 case 6:
3126 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3127 frags[c2s + 4], frags[c2s + 5]);
3128 if (draw_id) {
3129 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3130 frags[c2s + 4], frags[c2s + 5]];
3131 id = idByCurve(test, curve, PATH_QUAD);
3132 }
3133 break;
caryclark1049f122015-04-20 08:31:59 -07003134 case 7:
3135 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3136 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3137 if (draw_id) {
3138 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3139 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3140 id = idByCurve(test, curve, PATH_CONIC);
3141 }
3142 break;
caryclarkdac1d172014-06-17 05:15:38 -07003143 case 8:
3144 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3145 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3146 if (draw_id) {
3147 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3148 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3149 id = idByCurve(test, curve, PATH_CUBIC);
3150 }
3151 break;
3152 }
3153 if (id >= 0) {
3154 drawID(curve, id);
3155 }
3156 }
3157 if (collect_bounds) {
3158 break;
3159 }
caryclark54359292015-03-26 07:52:43 -07003160 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3161 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003162 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3163 }
3164 }
3165 if (!draw_intersectT) {
3166 break;
3167 }
3168 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003169 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3170 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003171 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3172 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3173 }
3174 }
3175 break;
3176 case REC_TYPE_SORT:
3177 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3178 continue;
3179 }
3180 ctx.lineWidth = 3;
3181 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3182 focus_enabled = true;
3183 switch (fragType) {
3184 case SORT_UNARY:
3185 case SORT_BINARY:
3186 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3187 drawCurve(curve);
3188 break;
3189 default:
3190 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3191 throw "stop execution";
3192 }
3193 break;
3194 case REC_TYPE_MARK:
3195 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3196 continue;
3197 }
3198 ctx.lineWidth = 3;
3199 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3200 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3201 focus_enabled = true;
3202 switch (fragType) {
3203 case MARK_LINE:
3204 case MARK_DONE_LINE:
3205 case MARK_UNSORTABLE_LINE:
3206 case MARK_SIMPLE_LINE:
3207 case MARK_SIMPLE_DONE_LINE:
3208 case MARK_DONE_UNARY_LINE:
3209 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3210 frags[5], frags[9]);
3211 if (draw_id) {
3212 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3213 frags[5], frags[9]);
3214 }
3215 break;
3216 case MARK_QUAD:
3217 case MARK_DONE_QUAD:
3218 case MARK_UNSORTABLE_QUAD:
3219 case MARK_SIMPLE_QUAD:
3220 case MARK_SIMPLE_DONE_QUAD:
3221 case MARK_DONE_UNARY_QUAD:
3222 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3223 frags[5], frags[6], frags[7], frags[11]);
3224 if (draw_id) {
3225 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3226 frags[5], frags[6], frags[7], frags[11]);
3227 }
3228 break;
3229 case MARK_CUBIC:
3230 case MARK_DONE_CUBIC:
3231 case MARK_UNSORTABLE_CUBIC:
3232 case MARK_SIMPLE_CUBIC:
3233 case MARK_SIMPLE_DONE_CUBIC:
3234 case MARK_DONE_UNARY_CUBIC:
3235 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3236 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3237 if (draw_id) {
3238 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3239 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3240 }
3241 break;
3242 case MARK_ANGLE_LAST:
3243 // FIXME: ignored for now
3244 break;
3245 default:
3246 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3247 throw "stop execution";
3248 }
3249 break;
3250 default:
3251 continue;
3252 }
3253 }
3254 switch (recType) {
3255 case REC_TYPE_SORT:
3256 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3257 break;
3258 }
3259 var angles = []; // use tangent lines to describe arcs
3260 var windFrom = [];
3261 var windTo = [];
3262 var opp = [];
3263 var minXY = Number.MAX_VALUE;
3264 var partial;
3265 focus_enabled = true;
3266 var someUnsortable = false;
3267 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3268 var fragType = records[recordIndex];
3269 var frags = records[recordIndex + 1];
3270 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3271 (fragType == SORT_BINARY && frags[16]);
3272 someUnsortable |= unsortable;
3273 switch (fragType) {
3274 case SORT_UNARY:
3275 case SORT_BINARY:
3276 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3277 break;
3278 default:
3279 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3280 throw "stop execution";
3281 }
3282 var dx = boundsWidth(partial);
3283 var dy = boundsHeight(partial);
3284 minXY = Math.min(minXY, dx * dx + dy * dy);
3285 if (collect_bounds) {
3286 continue;
3287 }
3288 angles.push(tangent(partial));
3289 var from = frags[12];
3290 var to = frags[12];
3291 var sgn = frags[10];
3292 if (sgn < 0) {
3293 from -= frags[11];
3294 } else if (sgn > 0) {
3295 to -= frags[11];
3296 }
3297 windFrom.push(from + (unsortable ? "!" : ""));
3298 windTo.push(to + (unsortable ? "!" : ""));
3299 opp.push(fragType == SORT_BINARY);
3300 if (draw_sort == 1) {
3301 drawOrder(partial, frags[12]);
3302 } else {
3303 drawOrder(partial, (recordIndex / 2) + 1);
3304 }
3305 }
3306 var radius = Math.sqrt(minXY) / 2 * scale;
3307 radius = Math.min(50, radius);
3308 var scaledRadius = radius / scale;
3309 var centerX = partial[0];
3310 var centerY = partial[1];
3311 if (collect_bounds) {
3312 if (focus_enabled) {
3313 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
3314 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
3315 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
3316 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
3317 }
3318 break;
3319 }
3320 break;
3321 default:
3322 break;
3323 }
3324 }
3325 if (collect_bounds) {
3326 return;
3327 }
3328 if (draw_log && logStart >= 0) {
3329 ctx.font = "normal 10px Arial";
3330 ctx.textAlign = "left";
3331 ctx.beginPath();
3332 var top = screenHeight - 20 - (logRange + 2) * 10;
3333 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
3334 ctx.fillStyle = "white";
3335 ctx.fill();
3336 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3337 if (logStart > 0) {
3338 ctx.fillText(lines[logStart - 1], 50, top + 8);
3339 }
3340 ctx.fillStyle = "black";
3341 for (var idx = 0; idx < logRange; ++idx) {
3342 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
3343 }
3344 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3345 if (logStart + logRange < lines.length) {
3346 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
3347 }
3348 }
3349 if (draw_legend) {
3350 var pos = 0;
caryclark54359292015-03-26 07:52:43 -07003351 var drawSomething = draw_add | draw_active | draw_angle | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07003352 // drawBox(pos++, "yellow", "black", opLetter, true, '');
3353 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
3354 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
3355 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
3356 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
3357 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
3358 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
3359 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
3360 drawBox(pos++, "black", "white",
3361 (new Array('P', 'P1', 'P2', 'P'))[draw_path], draw_path != 0, pathKey);
3362 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
3363 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
3364 draw_computed != 0, computedKey);
3365 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
3366 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
3367 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
3368 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
3369 if (curve_t) {
3370 drawCurveTControl();
3371 }
3372 ctx.font = "normal 20px Arial";
3373 ctx.fillStyle = "rgba(0,0,0, 0.3)";
3374 ctx.textAlign = "right";
3375 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
3376 }
3377 if (draw_hints) {
3378 ctx.font = "normal 10px Arial";
3379 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3380 ctx.textAlign = "right";
3381 var y = 4;
3382 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
3383 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
3384 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
3385 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07003386 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
3387 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
3388 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
3389 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
3390 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
3391 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
3392 }
3393}
3394
3395function drawBox(y, backC, foreC, str, enable, label) {
3396 ctx.beginPath();
3397 ctx.fillStyle = backC;
3398 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
3399 ctx.fill();
3400 ctx.font = "normal 16px Arial";
3401 ctx.fillStyle = foreC;
3402 ctx.textAlign = "center";
3403 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
3404 if (!enable) {
3405 ctx.fillStyle = "rgba(255,255,255, 0.5)";
3406 ctx.fill();
3407 }
3408 if (label != '') {
3409 ctx.font = "normal 9px Arial";
3410 ctx.fillStyle = "black";
3411 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
3412 }
3413}
3414
3415function drawCurveTControl() {
3416 ctx.lineWidth = 2;
3417 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
3418 ctx.beginPath();
3419 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
3420 ctx.stroke();
3421 var ty = 40 + curveT * (screenHeight - 80);
3422 ctx.beginPath();
3423 ctx.moveTo(screenWidth - 80, ty);
3424 ctx.lineTo(screenWidth - 85, ty - 5);
3425 ctx.lineTo(screenWidth - 85, ty + 5);
3426 ctx.lineTo(screenWidth - 80, ty);
3427 ctx.fillStyle = "rgba(0,0,0, 0.6)";
3428 ctx.fill();
3429 var num = curveT.toFixed(decimal_places);
3430 ctx.font = "normal 10px Arial";
3431 ctx.textAlign = "left";
3432 ctx.fillText(num, screenWidth - 78, ty);
3433}
3434
3435function ptInTControl() {
3436 var e = window.event;
3437 var tgt = e.target || e.srcElement;
3438 var left = tgt.offsetLeft;
3439 var top = tgt.offsetTop;
3440 var x = (e.clientX - left);
3441 var y = (e.clientY - top);
3442 if (x < screenWidth - 80 || x > screenWidth - 50) {
3443 return false;
3444 }
3445 if (y < 40 || y > screenHeight - 80) {
3446 return false;
3447 }
3448 curveT = (y - 40) / (screenHeight - 120);
3449 if (curveT < 0 || curveT > 1) {
3450 throw "stop execution";
3451 }
3452 return true;
3453}
3454
3455function drawTop() {
3456 if (tests[testIndex] == null) {
3457 var str = testDivs[testIndex].textContent;
3458 parse_all(str);
3459 var title = testDivs[testIndex].id.toString();
3460 testTitles[testIndex] = title;
3461 }
3462 init(tests[testIndex]);
3463 redraw();
3464}
3465
3466function redraw() {
3467 if (focus_on_selection) {
3468 collect_bounds = true;
3469 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3470 collect_bounds = false;
3471 if (focusXmin < focusXmax && focusYmin < focusYmax) {
3472 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
3473 }
3474 }
3475 ctx.beginPath();
3476 ctx.fillStyle = "white";
3477 ctx.rect(0, 0, screenWidth, screenHeight);
3478 ctx.fill();
3479 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3480}
3481
3482function dumpCurvePartial(test, id, t0, t1) {
3483 var curve = curveByID(test, id);
3484 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
3485 console.log("id=" + id + " " + name + "=" + curveToString(curve)
3486 + " t0=" + t0 + " t1=" + t1
3487 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
3488}
3489
3490function dumpAngleTest(test, id, t0, t1) {
3491 var curve = curveByID(test, id);
3492 console.log(" { {" + curveToString(curve) + "}, "
3493 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
3494}
3495
3496function dumpLogToConsole() {
3497 if (logStart < 0) {
3498 return;
3499 }
3500 var test = tests[testIndex];
3501 var recType = REC_TYPE_UNKNOWN;
3502 var records;
3503 for (var index = 0; index < test.length; index += 3) {
3504 var lastLineNo = test[index + 1];
3505 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
3506 recType = test[index];
3507 records = test[index + 2];
3508 break;
3509 }
3510 }
3511 if (recType == REC_TYPE_UNKNOWN) {
3512 return;
3513 }
3514 var lines = testLines[testIndex];
3515 for (var idx = 0; idx < logRange; ++idx) {
3516 var line = lines[logStart + idx];
3517 console.log(line);
3518 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3519 var fragType = records[recordIndex];
3520 var frags = records[recordIndex + 1];
3521 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07003522 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
3523 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
3524 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
3525 console.log("\nstatic IntersectData intersectDataSet[] = { //");
3526 dumpAngleTest(test, frags[0], frags[4], frags[5]);
3527 dumpAngleTest(test, frags[6], frags[10], frags[11]);
3528 dumpAngleTest(test, frags[12], frags[16], frags[17]);
3529 console.log("}; //");
3530 }
3531 }
3532 }
3533}
3534
3535var activeKey = 'a';
3536var pathKey = 'b';
3537var pathBackKey = 'B';
3538var centerKey = 'c';
3539var addKey = 'd';
3540var deriviativesKey = 'f';
3541var angleKey = 'g';
3542var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07003543var intersectionKey = 'i';
3544var intersectionBackKey = 'I';
3545var sequenceKey = 'j';
3546var midpointKey = 'k';
3547var logKey = 'l';
3548var logToConsoleKey = 'L';
3549var markKey = 'm';
3550var sortKey = 'o';
3551var opKey = 'p';
3552var opBackKey = 'P';
3553var computedKey = 'q';
3554var computedBackKey = 'Q';
3555var stepKey = 's';
3556var stepBackKey = 'S';
3557var intersectTKey = 't';
3558var curveTKey = 'u';
3559var controlLinesBackKey = 'V';
3560var controlLinesKey = 'v';
3561var ptsKey = 'x';
3562var xyKey = 'y';
3563var logCurvesKey = 'z';
3564var focusKey = '`';
3565var idKey = '.';
3566var retinaKey = '\\';
3567
3568function doKeyPress(evt) {
3569 var char = String.fromCharCode(evt.charCode);
3570 var focusWasOn = false;
3571 switch (char) {
3572 case '0':
3573 case '1':
3574 case '2':
3575 case '3':
3576 case '4':
3577 case '5':
3578 case '6':
3579 case '7':
3580 case '8':
3581 case '9':
3582 decimal_places = char - '0';
3583 redraw();
3584 break;
3585 case activeKey:
3586 draw_active ^= true;
3587 redraw();
3588 break;
3589 case addKey:
3590 draw_add ^= true;
3591 redraw();
3592 break;
3593 case angleKey:
caryclark54359292015-03-26 07:52:43 -07003594 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07003595 redraw();
3596 break;
3597 case angleBackKey:
3598 draw_angle = (draw_angle + 2) % 3;
3599 redraw();
3600 break;
3601 case centerKey:
3602 setScale(xmin, xmax, ymin, ymax);
3603 redraw();
3604 break;
3605 case controlLinesBackKey:
3606 control_lines = (control_lines + 3) % 4;
3607 redraw();
3608 break;
3609 case controlLinesKey:
3610 control_lines = (control_lines + 1) % 4;
3611 redraw();
3612 break;
3613 case computedBackKey:
3614 draw_computed = (draw_computed + 5) % 6;
3615 redraw();
3616 break;
3617 case computedKey:
3618 draw_computed = (draw_computed + 1) % 6;
3619 redraw();
3620 break;
3621 case curveTKey:
3622 curve_t ^= true;
3623 if (curve_t) {
3624 draw_legend = true;
3625 }
3626 redraw();
3627 break;
3628 case deriviativesKey:
3629 draw_deriviatives = (draw_deriviatives + 1) % 3;
3630 redraw();
3631 break;
3632 case focusKey:
3633 focus_on_selection ^= true;
3634 setScale(xmin, xmax, ymin, ymax);
3635 redraw();
3636 break;
caryclarkdac1d172014-06-17 05:15:38 -07003637 case idKey:
3638 draw_id ^= true;
3639 redraw();
3640 break;
3641 case intersectionBackKey:
3642 draw_intersection = (draw_intersection + 3) % 4;
3643 redraw();
3644 break;
3645 case intersectionKey:
3646 draw_intersection = (draw_intersection + 1) % 4;
3647 redraw();
3648 break;
3649 case intersectTKey:
3650 draw_intersectT ^= true;
3651 redraw();
3652 break;
3653 case logCurvesKey:
3654 logCurves(tests[testIndex]);
3655 break;
3656 case logKey:
3657 draw_log ^= true;
3658 redraw();
3659 break;
3660 case logToConsoleKey:
3661 if (draw_log) {
3662 dumpLogToConsole();
3663 }
3664 break;
3665 case markKey:
3666 draw_mark ^= true;
3667 redraw();
3668 break;
3669 case midpointKey:
3670 draw_midpoint ^= true;
3671 redraw();
3672 break;
3673 case opKey:
3674 draw_op = (draw_op + 1) % 3;
3675 redraw();
3676 break;
3677 case opBackKey:
3678 draw_op = (draw_op + 2) % 3;
3679 redraw();
3680 break;
3681 case pathKey:
3682 draw_path = (draw_path + 1) % 4;
3683 redraw();
3684 break;
3685 case pathBackKey:
3686 draw_path = (draw_path + 3) % 4;
3687 redraw();
3688 break;
3689 case ptsKey:
3690 pt_labels = (pt_labels + 1) % 3;
3691 redraw();
3692 break;
3693 case retinaKey:
3694 retina_scale ^= true;
3695 drawTop();
3696 break;
3697 case sequenceKey:
3698 draw_sequence ^= true;
3699 redraw();
3700 break;
3701 case sortKey:
3702 draw_sort = (draw_sort + 1) % 3;
3703 drawTop();
3704 break;
3705 case stepKey:
3706 step_limit++;
3707 if (step_limit > stepMax) {
3708 step_limit = stepMax;
3709 }
3710 redraw();
3711 break;
3712 case stepBackKey:
3713 step_limit--;
3714 if (step_limit < 0) {
3715 step_limit = 0;
3716 }
3717 redraw();
3718 break;
3719 case xyKey:
3720 debug_xy = (debug_xy + 1) % 3;
3721 redraw();
3722 break;
3723 case '-':
3724 focusWasOn = focus_on_selection;
3725 if (focusWasOn) {
3726 focus_on_selection = false;
3727 scale /= 1.2;
3728 } else {
3729 scale /= 2;
3730 calcLeftTop();
3731 }
3732 redraw();
3733 focus_on_selection = focusWasOn;
3734 break;
3735 case '=':
3736 case '+':
3737 focusWasOn = focus_on_selection;
3738 if (focusWasOn) {
3739 focus_on_selection = false;
3740 scale *= 1.2;
3741 } else {
3742 scale *= 2;
3743 calcLeftTop();
3744 }
3745 redraw();
3746 focus_on_selection = focusWasOn;
3747 break;
3748 case '?':
3749 draw_hints ^= true;
3750 if (draw_hints && !draw_legend) {
3751 draw_legend = true;
3752 }
3753 redraw();
3754 break;
3755 case '/':
3756 draw_legend ^= true;
3757 redraw();
3758 break;
3759 }
3760}
3761
3762function doKeyDown(evt) {
3763 var char = evt.keyCode;
3764 var preventDefault = false;
3765 switch (char) {
3766 case 37: // left arrow
3767 if (evt.shiftKey) {
3768 testIndex -= 9;
3769 }
3770 if (--testIndex < 0)
3771 testIndex = tests.length - 1;
3772 drawTop();
3773 preventDefault = true;
3774 break;
3775 case 39: // right arrow
3776 if (evt.shiftKey) {
3777 testIndex += 9;
3778 }
3779 if (++testIndex >= tests.length)
3780 testIndex = 0;
3781 drawTop();
3782 preventDefault = true;
3783 break;
3784 }
3785 if (preventDefault) {
3786 evt.preventDefault();
3787 return false;
3788 }
3789 return true;
3790}
3791
3792(function() {
3793 var hidden = "hidden";
3794
3795 // Standards:
3796 if (hidden in document)
3797 document.addEventListener("visibilitychange", onchange);
3798 else if ((hidden = "mozHidden") in document)
3799 document.addEventListener("mozvisibilitychange", onchange);
3800 else if ((hidden = "webkitHidden") in document)
3801 document.addEventListener("webkitvisibilitychange", onchange);
3802 else if ((hidden = "msHidden") in document)
3803 document.addEventListener("msvisibilitychange", onchange);
3804 // IE 9 and lower:
3805 else if ('onfocusin' in document)
3806 document.onfocusin = document.onfocusout = onchange;
3807 // All others:
3808 else
3809 window.onpageshow = window.onpagehide
3810 = window.onfocus = window.onblur = onchange;
3811
3812 function onchange (evt) {
3813 var v = 'visible', h = 'hidden',
3814 evtMap = {
3815 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
3816 };
3817
3818 evt = evt || window.event;
3819 if (evt.type in evtMap)
3820 document.body.className = evtMap[evt.type];
3821 else
3822 document.body.className = this[hidden] ? "hidden" : "visible";
3823 }
3824})();
3825
3826function calcXY() {
3827 var e = window.event;
3828 var tgt = e.target || e.srcElement;
3829 var left = tgt.offsetLeft;
3830 var top = tgt.offsetTop;
3831 mouseX = (e.clientX - left) / scale + srcLeft;
3832 mouseY = (e.clientY - top) / scale + srcTop;
3833}
3834
3835function calcLeftTop() {
3836 srcLeft = mouseX - screenWidth / 2 / scale;
3837 srcTop = mouseY - screenHeight / 2 / scale;
3838}
3839
3840var disableClick = false;
3841
3842function handleMouseClick() {
3843 if (disableClick) {
3844 return;
3845 }
3846 if (!curve_t || !ptInTControl()) {
3847 calcXY();
3848 calcLeftTop();
3849 }
3850 redraw();
3851// if (!curve_t || !ptInTControl()) {
3852// mouseX = screenWidth / 2 / scale + srcLeft;
3853// mouseY = screenHeight / 2 / scale + srcTop;
3854// }
3855}
3856
3857function handleMouseOver() {
3858 calcXY();
3859 if (debug_xy != 2) {
3860 return;
3861 }
3862 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
3863 ctx.beginPath();
3864 ctx.rect(300,100,num.length * 6,10);
3865 ctx.fillStyle="white";
3866 ctx.fill();
3867 ctx.font = "normal 10px Arial";
3868 ctx.fillStyle="black";
3869 ctx.textAlign = "left";
3870 ctx.fillText(num, 300, 108);
3871}
3872
3873function start() {
3874 for (var i = 0; i < testDivs.length; ++i) {
3875 tests[i] = null;
3876 }
3877 testIndex = 0;
3878 drawTop();
3879 window.addEventListener('keypress', doKeyPress, true);
3880 window.addEventListener('keydown', doKeyDown, true);
3881 window.onresize = function() {
3882 drawTop();
3883 }
3884 /*
3885 window.onpagehide = function() {
3886 disableClick = true;
3887 }
3888 */
3889 window.onpageshow = function () {
3890 disableClick = false;
3891 }
3892}
3893
3894</script>
3895</head>
3896
3897<body onLoad="start();">
3898<canvas id="canvas" width="750" height="500"
3899 onmousemove="handleMouseOver()"
3900 onclick="handleMouseClick()"
3901 ></canvas >
3902</body>
3903</html>