blob: f5482fd1f19ad7269feb2a84f93cd38353a0a077 [file] [log] [blame]
caryclarkdac1d172014-06-17 05:15:38 -07001<html>
2<head>
3<div height="0" hidden="true">
caryclark65f55312014-11-13 06:58:52 -08004<div id="fuzz763_1026368">
5 RunTestSet [fuzz763_1026368]
caryclarkdac1d172014-06-17 05:15:38 -07006
caryclark65f55312014-11-13 06:58:52 -08007{{27.3431454,27.3431454}, {29.6862907,25}, {33,25}},
8{{33,25}, {36.3137093,25}, {38.6568527,27.3431454}},
9{{38.6568527,27.3431454}, {41,29.6862907}, {41,33}},
10{{41,33}, {41,36.3137093}, {38.6568527,38.6568527}},
11{{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}},
12{{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}},
13{{38.6341171,38.6795731}, {38.6284409,38.6852493}, {38.6227531,38.6909218}},
14{{38.6227531,38.6909218}, {36.2775421,41.0320053}, {32.9638329,41.0290833}},
15{{32.9638329,41.0290833}, {29.6501274,41.0261612}, {27.3090477,38.6809464}},
16{{27.3090477,38.6809464}, {24.9679718,36.3357391}, {24.9708939,33.0220299}},
17{{24.9708939,33.0220299}, {24.973814,29.7083225}, {27.319025,27.3672428}},
18{{27.319025,27.3672428}, {27.3209743,27.3652973}, {27.3229256,27.3633518}},
19{{27.3229256,27.3633518}, {27.324995,27.3612823}, {27.3270645,27.3592148}},
20{{27.3270645,27.3592148}, {27.3312511,27.355032}, {27.3354416,27.3508568}},
21{{27.3354416,27.3508568}, {27.3332844,27.3530178}, {27.331131,27.3551788}},
22{{27.331131,27.3551788}, {27.3369579,27.3493824}, {27.3431988,27.3431988}},
23{{27.3431988,27.3431988}, {27.3431454,27.3431454}},
24{{38.6398277,38.6738319}, {38.6447258,38.6689186}},
25{{38.6447258,38.6689186}, {38.6447449,38.6689377}},
26{{38.6447449,38.6689377}, {38.6422882,38.6713867}, {38.6398277,38.6738319}},
caryclark19eb3b22014-07-18 05:08:14 -070027op union
caryclark65f55312014-11-13 06:58:52 -080028{{41,33}, {41,36.3137093}, {38.6568527,38.6568527}},
29{{38.6568527,38.6568527}, {36.3137093,41}, {33,41}},
30{{33,41}, {29.6862907,41}, {27.3431454,38.6568527}},
31{{27.3431454,38.6568527}, {25,36.3137093}, {25,33}},
32{{25,33}, {25,29.6862907}, {27.3431454,27.3431454}},
33{{27.3431454,27.3431454}, {29.6862907,25}, {33,25}},
34{{33,25}, {36.3137093,25}, {38.6568527,27.3431454}},
35{{38.6568527,27.3431454}, {41,29.6862907}, {41,33}},
36debugShowQuadIntersection wtTs[0]=1 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{33,25}} wnTs[0]=0 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}}
37debugShowQuadLineIntersection wtTs[0]=0 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{27.3431454,27.3431454}} wnTs[0]=1 {{27.3431988,27.3431988}, {27.3431454,27.3431454}}
38debugShowQuadIntersection wtTs[0]=1 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}} {{38.6568527,27.3431454}} wnTs[0]=0 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}}
39debugShowQuadIntersection wtTs[0]=1 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}} {{41,33}} wnTs[0]=0 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}}
40debugShowQuadIntersection wtTs[0]=1 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} {{38.6568527,38.6568527}} wnTs[0]=0 {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}}
41debugShowQuadIntersection wtTs[0]=1 {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}} {{38.6447449,38.6689377}} wnTs[0]=0 {{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}}
42debugShowQuadIntersection wtTs[0]=1 {{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}} {{38.6341171,38.6795731}} wnTs[0]=0 {{38.6341171,38.6795731}, {38.6284409,38.6852493}, {38.6227531,38.6909218}}
43debugShowQuadIntersection wtTs[0]=1 {{38.6341171,38.6795731}, {38.6284409,38.6852493}, {38.6227531,38.6909218}} {{38.6227531,38.6909218}} wnTs[0]=0 {{38.6227531,38.6909218}, {36.2775421,41.0320053}, {32.9638329,41.0290833}}
44debugShowQuadIntersection wtTs[0]=1 {{38.6227531,38.6909218}, {36.2775421,41.0320053}, {32.9638329,41.0290833}} {{32.9638329,41.0290833}} wnTs[0]=0 {{32.9638329,41.0290833}, {29.6501274,41.0261612}, {27.3090477,38.6809464}}
45debugShowQuadIntersection wtTs[0]=1 {{32.9638329,41.0290833}, {29.6501274,41.0261612}, {27.3090477,38.6809464}} {{27.3090477,38.6809464}} wnTs[0]=0 {{27.3090477,38.6809464}, {24.9679718,36.3357391}, {24.9708939,33.0220299}}
46debugShowQuadIntersection wtTs[0]=1 {{27.3090477,38.6809464}, {24.9679718,36.3357391}, {24.9708939,33.0220299}} {{24.9708939,33.0220299}} wnTs[0]=0 {{24.9708939,33.0220299}, {24.973814,29.7083225}, {27.319025,27.3672428}}
47debugShowQuadIntersection wtTs[0]=1 {{24.9708939,33.0220299}, {24.973814,29.7083225}, {27.319025,27.3672428}} {{27.319025,27.3672428}} wnTs[0]=0 {{27.319025,27.3672428}, {27.3209743,27.3652973}, {27.3229256,27.3633518}}
48debugShowQuadIntersection wtTs[0]=1 {{27.319025,27.3672428}, {27.3209743,27.3652973}, {27.3229256,27.3633518}} {{27.3229256,27.3633518}} wnTs[0]=0 {{27.3229256,27.3633518}, {27.324995,27.3612823}, {27.3270645,27.3592148}}
49debugShowQuadIntersection wtTs[0]=1 {{27.3229256,27.3633518}, {27.324995,27.3612823}, {27.3270645,27.3592148}} {{27.3270645,27.3592148}} wnTs[0]=0 {{27.3270645,27.3592148}, {27.3312511,27.355032}, {27.3354416,27.3508568}}
50debugShowQuadIntersection wtTs[0]=1 {{27.3270645,27.3592148}, {27.3312511,27.355032}, {27.3354416,27.3508568}} {{27.3354416,27.3508568}} wnTs[0]=0 {{27.3354416,27.3508568}, {27.3332844,27.3530178}, {27.331131,27.3551788}}
51debugShowQuadIntersection no intersect {{27.3270645,27.3592148}, {27.3312511,27.355032}, {27.3354416,27.3508568}} {{27.331131,27.3551788}, {27.3369579,27.3493824}, {27.3431988,27.3431988}}
52debugShowQuadIntersection wtTs[0]=1 {{27.3354416,27.3508568}, {27.3332844,27.3530178}, {27.331131,27.3551788}} {{27.331131,27.3551788}} wnTs[0]=0 {{27.331131,27.3551788}, {27.3369579,27.3493824}, {27.3431988,27.3431988}}
53debugShowQuadLineIntersection wtTs[0]=1 {{27.331131,27.3551788}, {27.3369579,27.3493824}, {27.3431988,27.3431988}} {{27.3431988,27.3431988}} wnTs[0]=0 {{27.3431988,27.3431988}, {27.3431454,27.3431454}}
54debugShowQuadIntersection wtTs[0]=0 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{27.3431454,27.3431454}} wnTs[0]=1 {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
55debugShowQuadIntersection wtTs[0]=0 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{27.3431454,27.3431454}} wtTs[1]=1 {{33,25}} wnTs[0]=0 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} wnTs[1]=1
56debugShowQuadIntersection wtTs[0]=1 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{33,25}} wnTs[0]=0 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}}
57debugShowQuadIntersection wtTs[0]=0 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}} {{33,25}} wnTs[0]=1 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}}
58debugShowQuadIntersection wtTs[0]=0 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}} {{33,25}} wtTs[1]=1 {{38.6568527,27.3431454}} wnTs[0]=0 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}} wnTs[1]=1
59debugShowQuadIntersection wtTs[0]=1 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}} {{38.6568527,27.3431454}} wnTs[0]=0 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}}
60debugShowQuadIntersection wtTs[0]=1 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}} {{41,33}} wnTs[0]=0 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}}
61debugShowQuadIntersection wtTs[0]=0 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}} {{38.6568527,27.3431454}} wnTs[0]=1 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}}
62debugShowQuadIntersection wtTs[0]=0 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}} {{38.6568527,27.3431454}} wtTs[1]=1 {{41,33}} wnTs[0]=0 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}} wnTs[1]=1
63debugShowQuadIntersection wtTs[0]=0 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} {{41,33}} wtTs[1]=1 {{38.6568527,38.6568527}} wnTs[0]=0 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} wnTs[1]=1
64debugShowQuadIntersection wtTs[0]=1 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} {{38.6568527,38.6568527}} wnTs[0]=0 {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}}
65debugShowQuadIntersection wtTs[0]=0 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} {{41,33}} wnTs[0]=1 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}}
66debugShowQuadIntersection wtTs[0]=0 {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}} {{38.6568527,38.6568527}} wnTs[0]=1 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}}
67debugShowQuadIntersection wtTs[0]=0 {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}} {{38.6568527,38.6568527}} wnTs[0]=0 {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}}
68debugShowQuadIntersection wtTs[0]=0.0149880862 {{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}} {{38.6445847,38.6690979}} wnTs[0]=0.00261623 {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}}
69debugShowQuadIntersection no intersect {{38.6341171,38.6795731}, {38.6284409,38.6852493}, {38.6227531,38.6909218}} {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}}
70debugShowQuadIntersection no intersect {{38.6227531,38.6909218}, {36.2775421,41.0320053}, {32.9638329,41.0290833}} {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}}
71debugShowQuadIntersection no intersect {{38.6227531,38.6909218}, {36.2775421,41.0320053}, {32.9638329,41.0290833}} {{33,41}, {29.6862907,41}, {27.3431454,38.6568527}}
72debugShowQuadIntersection no intersect {{32.9638329,41.0290833}, {29.6501274,41.0261612}, {27.3090477,38.6809464}} {{33,41}, {29.6862907,41}, {27.3431454,38.6568527}}
73debugShowQuadIntersection no intersect {{27.3090477,38.6809464}, {24.9679718,36.3357391}, {24.9708939,33.0220299}} {{27.3431454,38.6568527}, {25,36.3137093}, {25,33}}
74debugShowQuadIntersection no intersect {{24.9708939,33.0220299}, {24.973814,29.7083225}, {27.319025,27.3672428}} {{27.3431454,38.6568527}, {25,36.3137093}, {25,33}}
75debugShowQuadIntersection no intersect {{24.9708939,33.0220299}, {24.973814,29.7083225}, {27.319025,27.3672428}} {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
76debugShowQuadIntersection no intersect {{27.319025,27.3672428}, {27.3209743,27.3652973}, {27.3229256,27.3633518}} {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
77debugShowQuadIntersection no intersect {{27.3229256,27.3633518}, {27.324995,27.3612823}, {27.3270645,27.3592148}} {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
78debugShowQuadIntersection no intersect {{27.3270645,27.3592148}, {27.3312511,27.355032}, {27.3354416,27.3508568}} {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
79debugShowQuadIntersection wtTs[0]=0 {{27.3354416,27.3508568}, {27.3332844,27.3530178}, {27.331131,27.3551788}} {{27.3354416,27.3508568}} wtTs[1]=1 {{27.331131,27.3551788}} wnTs[0]=0.998355 {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}} wnTs[1]=0.99743327
80debugShowQuadIntersection wtTs[0]=0.0266527086 {{27.331131,27.3551788}, {27.3369579,27.3493824}, {27.3431988,27.3431988}} {{27.3314419,27.3548698}} wnTs[0]=0.997499 {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
81debugShowQuadLineIntersection wtTs[0]=1 {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}} {{27.3431454,27.3431454}} wnTs[0]=1 {{27.3431988,27.3431988}, {27.3431454,27.3431454}}
82debugShowQuadLineIntersection wtTs[0]=0 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{27.3431454,27.3431454}} wnTs[0]=1 {{27.3431988,27.3431988}, {27.3431454,27.3431454}}
83debugShowQuadLineIntersection no intersect {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}} {{38.6398277,38.6738319}, {38.6447258,38.6689186}}
84debugShowQuadLineIntersection wtTs[0]=1 {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}} {{38.6447449,38.6689377}} wnTs[0]=1 {{38.6447258,38.6689186}, {38.6447449,38.6689377}}
85debugShowQuadIntersection wtTs[0]=1 {{38.6568527,38.6568527}, {38.6510239,38.6626816}, {38.6447449,38.6689377}} {{38.6447449,38.6689377}} wnTs[0]=0 {{38.6447449,38.6689377}, {38.6422882,38.6713867}, {38.6398277,38.6738319}}
86debugShowQuadLineIntersection no intersect {{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}} {{38.6398277,38.6738319}, {38.6447258,38.6689186}}
87debugShowQuadLineIntersection wtTs[0]=0 {{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}} {{38.6447449,38.6689377}} wnTs[0]=1 {{38.6447258,38.6689186}, {38.6447449,38.6689377}}
88debugShowQuadIntersection wtTs[0]=0 {{38.6447449,38.6689377}, {38.6394348,38.6742554}, {38.6341171,38.6795731}} {{38.6447449,38.6689377}} wnTs[0]=0 {{38.6447449,38.6689377}, {38.6422882,38.6713867}, {38.6398277,38.6738319}}
89debugShowQuadIntersection wtTs[0]=1 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} {{38.6568527,38.6568527}} wnTs[0]=0 {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}}
90debugShowQuadIntersection wtTs[0]=0 {{41,33}, {41,36.3137093}, {38.6568527,38.6568527}} {{41,33}} wnTs[0]=1 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}}
91debugShowQuadIntersection wtTs[0]=1 {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}} {{33,41}} wnTs[0]=0 {{33,41}, {29.6862907,41}, {27.3431454,38.6568527}}
92debugShowQuadIntersection wtTs[0]=1 {{33,41}, {29.6862907,41}, {27.3431454,38.6568527}} {{27.3431454,38.6568527}} wnTs[0]=0 {{27.3431454,38.6568527}, {25,36.3137093}, {25,33}}
93debugShowQuadIntersection wtTs[0]=1 {{27.3431454,38.6568527}, {25,36.3137093}, {25,33}} {{25,33}} wnTs[0]=0 {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}}
94debugShowQuadIntersection wtTs[0]=1 {{25,33}, {25,29.6862907}, {27.3431454,27.3431454}} {{27.3431454,27.3431454}} wnTs[0]=0 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}}
95debugShowQuadIntersection wtTs[0]=1 {{27.3431454,27.3431454}, {29.6862907,25}, {33,25}} {{33,25}} wnTs[0]=0 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}}
96debugShowQuadIntersection wtTs[0]=1 {{33,25}, {36.3137093,25}, {38.6568527,27.3431454}} {{38.6568527,27.3431454}} wnTs[0]=0 {{38.6568527,27.3431454}, {41,29.6862907}, {41,33}}
97debugShowQuadLineIntersection no intersect {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}} {{38.6398277,38.6738319}, {38.6447258,38.6689186}}
98debugShowQuadLineIntersection no intersect {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}} {{38.6447258,38.6689186}, {38.6447449,38.6689377}}
99debugShowQuadIntersection wtTs[0]=0.00258220891 {{38.6568527,38.6568527}, {36.3137093,41}, {33,41}} {{38.6447449,38.6689377}} wtTs[1]=0.00362998223 {{38.6398277,38.6738319}} wnTs[0]=0 {{38.6447449,38.6689377}, {38.6422882,38.6713867}, {38.6398277,38.6738319}} wnTs[1]=1
100debugShowLineIntersection wtTs[0]=1 {{38.6398277,38.6738319}, {38.6447258,38.6689186}} {{38.6447258,38.6689186}} wnTs[0]=0 {{38.6447258,38.6689186}, {38.6447449,38.6689377}}
101debugShowQuadLineIntersection wtTs[0]=1 {{38.6447449,38.6689377}, {38.6422882,38.6713867}, {38.6398277,38.6738319}} {{38.6398277,38.6738319}} wnTs[0]=0 {{38.6398277,38.6738319}, {38.6447258,38.6689186}}
102debugShowQuadLineIntersection wtTs[0]=0 {{38.6447449,38.6689377}, {38.6422882,38.6713867}, {38.6398277,38.6738319}} {{38.6447449,38.6689377}} wnTs[0]=1 {{38.6447258,38.6689186}, {38.6447449,38.6689377}}
103SkOpSegment::debugShowTs - id=0 [o=24,16 t=0 27.3431454,27.3431454 w=1 o=0] [o=26,1 t=1 33,25 w=1 o=0]
104SkOpSegment::debugShowTs o id=25 [o=24,16 t=0 27.3431454,27.3431454 w=1 o=0] [o=26,1 t=1 33,25 w=1 o=0] operand
105SkOpSegment::debugShowTs + id=0 [o=24,16 t=0 27.3431454,27.3431454 w=1 o=0] [o=26,1 t=1 33,25 w=1 o=0]
106SkOpSegment::debugShowTs o id=25 [o=24,16 t=0 27.3431454,27.3431454 w=1 o=0] [o=26,1 t=1 33,25 w=1 o=0] operand
107SkOpSegment::debugShowTs - id=1 [o=25,0 t=0 33,25 w=1 o=0] [o=27,2 t=1 38.6568527,27.3431454 w=1 o=0]
108SkOpSegment::debugShowTs o id=26 [o=25,0 t=0 33,25 w=1 o=0] [o=27,2 t=1 38.6568527,27.3431454 w=1 o=0] operand
109SkOpSegment::debugShowTs + id=1 [o=25,0 t=0 33,25 w=1 o=0] [o=27,2 t=1 38.6568527,27.3431454 w=1 o=0]
110SkOpSegment::debugShowTs o id=26 [o=25,0 t=0 33,25 w=1 o=0] [o=27,2 t=1 38.6568527,27.3431454 w=1 o=0] operand
111SkOpSegment::debugShowTs - id=2 [o=26,1 t=0 38.6568527,27.3431454 w=1 o=0] [o=20,3 t=1 41,33 w=1 o=0]
112SkOpSegment::debugShowTs o id=27 [o=26,1 t=0 38.6568527,27.3431454 w=1 o=0] [o=20,3 t=1 41,33 w=1 o=0] operand
113SkOpSegment::debugShowTs + id=2 [o=26,1 t=0 38.6568527,27.3431454 w=1 o=0] [o=20,3 t=1 41,33 w=1 o=0]
114SkOpSegment::debugShowTs o id=27 [o=26,1 t=0 38.6568527,27.3431454 w=1 o=0] [o=20,3 t=1 41,33 w=1 o=0] operand
115SkOpSegment::debugShowTs - id=3 [o=27,2 t=0 41,33 w=1 o=0] [o=21,4 t=1 38.6568527,38.6568527 w=1 o=0]
116SkOpSegment::debugShowTs o id=20 [o=27,2 t=0 41,33 w=1 o=0] [o=21,4 t=1 38.6568527,38.6568527 w=1 o=0] operand
117SkOpSegment::debugShowTs + id=3 [o=27,2 t=0 41,33 w=1 o=0] [o=21,4 t=1 38.6568527,38.6568527 w=1 o=0]
118SkOpSegment::debugShowTs o id=20 [o=27,2 t=0 41,33 w=1 o=0] [o=21,4 t=1 38.6568527,38.6568527 w=1 o=0] operand
119SkOpSegment::debugShowTs - id=14 [o=13 t=0 27.3354416,27.3508568 w=1 o=0] [o=15 t=1 27.331131,27.3551788 w=1 o=0]
120SkOpSegment::debugShowTs o id=24 [o=23 t=0 25,33 w=1 o=0] [o=15 t=0.997 27.3314419,27.3548698 w=1 o=0] [o=25,16,0 t=1 27.3431454,27.3431454 w=1 o=0] operand
121SkOpSegment::addTPair addTPair this=14 0 other=24 0.998354892
122SkOpSegment::addTPair id=14 lower=0 upper=1 other=24 oLower=2 oUpper=2
123SkOpSegment::addTPair addTPair this=24 0.99743327 other=14 1
124SkOpSegment::addTPair id=24 lower=1 upper=1 other=14 oLower=2 oUpper=3
125SkOpSegment::debugShowTs + id=14 [o=24,13 t=0 27.3354416,27.3508568 w=1 o=0] [o=24,15 t=1 27.331131,27.3551788 w=1 o=0]
126SkOpSegment::debugShowTs o id=24 [o=23 t=0 25,33 w=1 o=0] [o=14 t=0.997 27.331131,27.3551788 w=1 o=0] [o=15 t=0.997 27.3314419,27.3548698 w=1 o=0] [o=14 t=0.998 27.3354416,27.3508568 w=1 o=0] [o=25,16,0 t=1 27.3431454,27.3431454 w=1 o=0] operand
127SkOpSegment::debugShowTs - id=21 [o=20,4,3 t=0 38.6568527,38.6568527 w=1 o=0] [o=5 t=0.00262 38.6445847,38.6690979 w=1 o=0] [o=22 t=1 33,41 w=1 o=0] operand
128SkOpSegment::debugShowTs o id=19 [o=18,5,4 t=0 38.6447449,38.6689377 w=1 o=0] [o=17 t=1 38.6398277,38.6738319 w=1 o=0]
129SkOpSegment::addTPair addTPair this=21 0.00258220891 other=19 0
130SkOpSegment::addTPair id=21 lower=3 upper=3 other=19 oLower=0 oUpper=3
131SkOpSegment::addTPair addTPair this=19 1 other=21 0.00362998223
132SkOpSegment::addTPair id=19 lower=4 upper=5 other=21 oLower=5 oUpper=5
133SkOpSegment::debugShowTs + id=21 [o=20,4,3 t=0 38.6568527,38.6568527 w=1 o=0] [o=19 t=0.00258 38.6447449,38.6689377 w=1 o=0] [o=5 t=0.00262 38.6445847,38.6690979 w=1 o=0] [o=19 t=0.00363 38.6398277,38.6738319 w=1 o=0] [o=22 t=1 33,41 w=1 o=0] operand
134SkOpSegment::debugShowTs o id=19 [o=21,18,5,4 t=0 38.6447449,38.6689377 w=1 o=0] [o=21,17 t=1 38.6398277,38.6738319 w=1 o=0]
135SkOpContour::calcCoincidentWinding count=5
136SkOpSegment::debugShowTs p id=0 [o=24,16 t=0 27.3431454,27.3431454 w=1 o=1] [o=26,1 t=1 33,25 w=1 o=0]
137SkOpSegment::debugShowTs o id=25 [o=24,16 t=0 27.3431454,27.3431454 w=0 o=0] [o=26,1 t=1 33,25 w=1 o=0] operand done
138SkOpSegment::debugShowTs p id=1 [o=25,0 t=0 33,25 w=1 o=1] [o=27,2 t=1 38.6568527,27.3431454 w=1 o=0]
139SkOpSegment::debugShowTs o id=26 [o=25,0 t=0 33,25 w=0 o=0] [o=27,2 t=1 38.6568527,27.3431454 w=1 o=0] operand done
140SkOpSegment::debugShowTs p id=2 [o=26,1 t=0 38.6568527,27.3431454 w=1 o=1] [o=20,3 t=1 41,33 w=1 o=0]
141SkOpSegment::debugShowTs o id=27 [o=26,1 t=0 38.6568527,27.3431454 w=0 o=0] [o=20,3 t=1 41,33 w=1 o=0] operand done
142SkOpSegment::debugShowTs p id=3 [o=27,2 t=0 41,33 w=1 o=1] [o=21,4 t=1 38.6568527,38.6568527 w=1 o=0]
143SkOpSegment::debugShowTs o id=20 [o=27,2 t=0 41,33 w=0 o=0] [o=21,4 t=1 38.6568527,38.6568527 w=1 o=0] operand done
144SkOpSegment::debugShowTs p id=14 [o=24,13 t=0 27.3354416,27.3508568 w=1 o=-1] [o=24,15 t=1 27.331131,27.3551788 w=1 o=0]
145SkOpSegment::debugShowTs o id=24 [o=23 t=0 25,33 w=0 o=0] [o=14 t=0.997 27.331131,27.3551788 w=0 o=0] [o=15 t=0.997 27.3314419,27.3548698 w=0 o=0] [o=14 t=0.998 27.3354416,27.3508568 w=1 o=0] [o=25,16,0 t=1 27.3431454,27.3431454 w=1 o=0] operand
146SkOpContour::calcCoincidentWinding count=1
147SkOpSegment::debugShowTs p id=21 [o=20,4,3 t=0 38.6568527,38.6568527 w=1 o=0] [o=19 t=0.00258 38.6447449,38.6689377 w=1 o=1] [o=5 t=0.00262 38.6445847,38.6690979 w=1 o=1] [o=19 t=0.00363 38.6398277,38.6738319 w=1 o=0] [o=22 t=1 33,41 w=1 o=0] operand
148SkOpSegment::debugShowTs o id=19 [o=21,18,5,4 t=0 38.6447449,38.6689377 w=0 o=0] [o=21,17 t=1 38.6398277,38.6738319 w=1 o=0] done
149SkOpSegment::checkEnds id=4 missing t=1 other=21 otherT=0.00258220891 pt=(38.6447449,38.6689377)
150SkOpSegment::addTPair addTPair this=4 1 other=21 0.00258220891
151SkOpSegment::addTPair id=4 lower=3 upper=6 other=21 oLower=3 oUpper=4
152SkOpSegment::checkEnds id=5 missing t=0 other=21 otherT=0.00258220891 pt=(38.6447449,38.6689377)
153SkOpSegment::addTPair addTPair this=5 0 other=21 0.00258220891
154SkOpSegment::addTPair id=5 lower=0 upper=3 other=21 oLower=3 oUpper=5
155SkOpSegment::checkEnds id=13 missing t=1 other=24 otherT=0.998354892 pt=(27.3354416,27.3508568)
156SkOpSegment::addTPair addTPair this=13 1 other=24 0.998354892
157SkOpSegment::addTPair id=13 lower=1 upper=2 other=24 oLower=3 oUpper=4
158SkOpSegment::checkEnds id=15 missing t=0 other=24 otherT=0.99743327 pt=(27.331131,27.3551788)
159SkOpSegment::addTPair addTPair this=15 0 other=24 0.99743327
160SkOpSegment::addTPair id=15 lower=0 upper=1 other=24 oLower=1 oUpper=2
161SkOpSegment::checkEnds id=21 missing t=0.00362998223 other=17 otherT=0 pt=(38.6398277,38.6738319)
162SkOpSegment::addTPair addTPair this=21 0.00362998223 other=17 0
163SkOpSegment::addTPair id=21 lower=7 upper=8 other=17 oLower=0 oUpper=1
164SkOpSegment::addTPair addTPair this=0 0 other=25 0
165SkOpSegment::addTPair id=0 lower=0 upper=2 other=25 oLower=0 oUpper=2
166SkOpSegment::addTPair addTPair duplicate this=0 0 other=25 0
167SkOpSegment::addTPair addTPair this=3 1 other=20 1
168SkOpSegment::addTPair id=3 lower=2 upper=4 other=20 oLower=2 oUpper=4
169SkOpSegment::addTPair addTPair duplicate this=3 1 other=20 1
170SkOpSegment::addTPair addTPair this=21 0.00258220891 other=18 1
171SkOpSegment::addTPair id=21 lower=3 upper=6 other=18 oLower=1 oUpper=4
172SkOpSegment::addTPair addTPair duplicate this=18 1 other=21 0.00258220891
173SkOpContour::joinCoincidence count=5
174SkOpContour::joinCoincidence count=1
175SkOpSegment::sortAngles [0] tStart=0 [1]
176SkOpAngle::after [0/1] 2/1 tStart=0 tEnd=1 < [16/1] 27/27 tStart=1 tEnd=0 < [24/2] 17/21 tStart=1 tEnd=0.998354892 F 4
177SkOpSegment::sortAngles [0] tStart=1 [4]
178SkOpSegment::sortAngles [1] tStart=1 [3]
179SkOpSegment::sortAngles [2] tStart=1 [3]
180SkOpSegment::sortAngles [3] tStart=1 [3]
181SkOpAngle::after [3/2] 1/5 tStart=1 tEnd=0 < [4/1] 18/17 tStart=0 tEnd=1 < [21/1] 21/17 tStart=0 tEnd=0.00258220891 T 11
182SkOpSegment::sortAngles [4] tStart=1 [3]
183SkOpAngle::after [4/2] 1/1 tStart=1 tEnd=0 < [21/3] 21/21 tStart=0.00258220891 tEnd=0.0026162254 < [21/2] 1/1 tStart=0.00258220891 tEnd=0 T 5
184SkOpAngle::after [4/2] 1/1 tStart=1 tEnd=0 < [18/1] 11/11 tStart=1 tEnd=0 < [21/3] 21/21 tStart=0.00258220891 tEnd=0.0026162254 T 4
185SkOpAngle::after [4/2] 1/1 tStart=1 tEnd=0 < [5/1] 21/21 tStart=0 tEnd=0.0149880862 < [18/1] 11/11 tStart=1 tEnd=0 F 4
186SkOpAngle::after [18/1] 11/11 tStart=1 tEnd=0 < [5/1] 21/21 tStart=0 tEnd=0.0149880862 < [21/3] 21/21 tStart=0.00258220891 tEnd=0.0026162254 T 7
187SkOpSegment::sortAngles [5] tStart=0.0149880862 [4]
188SkOpAngle::after [5/2] 1/1 tStart=0.0149880862 tEnd=0 < [21/4] 1/1 tStart=0.0026162254 tEnd=0.00258220891 < [5/3] 21/21 tStart=0.0149880862 tEnd=1 T 12
189SkOpAngle::after [5/2] 1/1 tStart=0.0149880862 tEnd=0 < [21/5] 17/17 tStart=0.0026162254 tEnd=0.00362998223 < [21/4] 1/1 tStart=0.0026162254 tEnd=0.00258220891 F 5
190SkOpAngle::after [21/4] 1/1 tStart=0.0026162254 tEnd=0.00258220891 < [21/5] 17/17 tStart=0.0026162254 tEnd=0.00362998223 < [5/3] 21/21 tStart=0.0149880862 tEnd=1 T 4
191SkOpSegment::sortAngles [13] tStart=1 [1]
192SkOpAngle::after [13/1] 17/17 tStart=1 tEnd=0 < [14/1] 21/21 tStart=0 tEnd=1 < [24/1] 5/5 tStart=0.998354892 tEnd=1 T 4
193SkOpSegment::sortAngles [14] tStart=1 [3]
194SkOpSegment::sortAngles [15] tStart=0.0266527086 [2]
195SkOpSegment::sortAngles [21] tStart=0.00362998223 [8]
196SkOpAngle::after [21/6] 1/1 tStart=0.00362998223 tEnd=0.0026162254 < [17/1] 5/5 tStart=0 tEnd=1 < [21/7] 17/17 tStart=0.00362998223 tEnd=1 T 4
197SkOpSegment::debugShowActiveSpans id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 (27.3431454,27.3431454) tEnd=1 other=25 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=1
198SkOpSegment::debugShowActiveSpans id=1 (33,25 36.3137093,25 38.6568527,27.3431454) t=0 (33,25) tEnd=1 other=25 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=1
199SkOpSegment::debugShowActiveSpans id=2 (38.6568527,27.3431454 41,29.6862907 41,33) t=0 (38.6568527,27.3431454) tEnd=1 other=26 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=1
200SkOpSegment::debugShowActiveSpans id=3 (41,33 41,36.3137093 38.6568527,38.6568527) t=0 (41,33) tEnd=1 other=27 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=1
201SkOpSegment::debugShowActiveSpans id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 (38.6568527,38.6568527) tEnd=1 other=21 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
202SkOpSegment::debugShowActiveSpans id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0 (38.6447449,38.6689377) tEnd=0.0149880862 other=21 otherT=0.00258220891 otherIndex=4 windSum=? windValue=1 oppValue=0
203SkOpSegment::debugShowActiveSpans id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0.0149880862 (38.6445847,38.6690979) tEnd=1 other=21 otherT=0.0026162254 otherIndex=7 windSum=? windValue=1 oppValue=0
204SkOpSegment::debugShowActiveSpans id=6 (38.6341171,38.6795731 38.6284409,38.6852493 38.6227531,38.6909218) t=0 (38.6341171,38.6795731) tEnd=1 other=5 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
205SkOpSegment::debugShowActiveSpans id=7 (38.6227531,38.6909218 36.2775421,41.0320053 32.9638329,41.0290833) t=0 (38.6227531,38.6909218) tEnd=1 other=6 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
206SkOpSegment::debugShowActiveSpans id=8 (32.9638329,41.0290833 29.6501274,41.0261612 27.3090477,38.6809464) t=0 (32.9638329,41.0290833) tEnd=1 other=7 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
207SkOpSegment::debugShowActiveSpans id=9 (27.3090477,38.6809464 24.9679718,36.3357391 24.9708939,33.0220299) t=0 (27.3090477,38.6809464) tEnd=1 other=8 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
208SkOpSegment::debugShowActiveSpans id=10 (24.9708939,33.0220299 24.973814,29.7083225 27.319025,27.3672428) t=0 (24.9708939,33.0220299) tEnd=1 other=9 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
209SkOpSegment::debugShowActiveSpans id=11 (27.319025,27.3672428 27.3209743,27.3652973 27.3229256,27.3633518) t=0 (27.319025,27.3672428) tEnd=1 other=10 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
210SkOpSegment::debugShowActiveSpans id=12 (27.3229256,27.3633518 27.324995,27.3612823 27.3270645,27.3592148) t=0 (27.3229256,27.3633518) tEnd=1 other=11 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
211SkOpSegment::debugShowActiveSpans id=13 (27.3270645,27.3592148 27.3312511,27.355032 27.3354416,27.3508568) t=0 (27.3270645,27.3592148) tEnd=1 other=12 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
212SkOpSegment::debugShowActiveSpans id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 (27.3354416,27.3508568) tEnd=1 other=24 otherT=0.998354892 otherIndex=5 windSum=? windValue=1 oppValue=-1
213SkOpSegment::debugShowActiveSpans id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0 (27.331131,27.3551788) tEnd=0.0266527086 other=24 otherT=0.99743327 otherIndex=1 windSum=? windValue=1 oppValue=0
214SkOpSegment::debugShowActiveSpans id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0.0266527086 (27.3314419,27.3548698) tEnd=1 other=24 otherT=0.997499486 otherIndex=3 windSum=? windValue=1 oppValue=0
215SkOpSegment::debugShowActiveSpans id=16 (27.3431988,27.3431988 27.3431454,27.3431454) t=0 (27.3431988,27.3431988) tEnd=1 other=15 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
216SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 (38.6568527,38.6568527) tEnd=0.00258220891 other=20 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
217SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00258220891 (38.6447449,38.6689377) tEnd=0.0026162254 other=18 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=1
218SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.0026162254 (38.6445847,38.6690979) tEnd=0.00362998223 other=5 otherT=0.0149880862 otherIndex=4 windSum=? windValue=1 oppValue=1
219SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00362998223 (38.6398277,38.6738319) tEnd=1 other=17 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
220SkOpSegment::debugShowActiveSpans id=22 (33,41 29.6862907,41 27.3431454,38.6568527) t=0 (33,41) tEnd=1 other=21 otherT=1 otherIndex=10 windSum=? windValue=1 oppValue=0
221SkOpSegment::debugShowActiveSpans id=23 (27.3431454,38.6568527 25,36.3137093 25,33) t=0 (27.3431454,38.6568527) tEnd=1 other=22 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
222SkOpSegment::debugShowActiveSpans id=24 (25,33 25,29.6862907 27.3431454,27.3431454) t=0.998354892 (27.3354416,27.3508568) tEnd=1 other=13 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
223SkOpSegment::debugShowActiveSpans id=17 (38.6398277,38.6738319 38.6447258,38.6689186) t=0 (38.6398277,38.6738319) tEnd=1 other=21 otherT=0.00362998223 otherIndex=8 windSum=? windValue=1 oppValue=0
224SkOpSegment::findTop
225SkOpAngle::dumpOne [0/2] next=1/1 sect=16/17 s=1 [4] e=0 [2] sgn=1 windVal=1 windSum=? oppVal=1 oppSum=?
226SkOpAngle::dumpOne [1/1] next=0/2 sect=30/29 s=0 [0] e=1 [2] sgn=-1 windVal=1 windSum=? oppVal=1 oppSum=? stop
227SkOpSegment::markWinding id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [1] (27.3431454,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
228SkOpSegment::markWinding id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [0] (27.3431454,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
229SkOpSegment::markWinding id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [2] (27.3431454,27.3431454) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
230SkOpSegment::nextChase mismatched signs
231SkOpSegment::markWinding id=1 (33,25 36.3137093,25 38.6568527,27.3431454) t=0 [0] (33,25) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
232SkOpSegment::markWinding id=1 (33,25 36.3137093,25 38.6568527,27.3431454) t=0 [1] (33,25) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
233SkOpSegment::nextChase mismatched signs
234SkOpSegment::markWinding id=2 (38.6568527,27.3431454 41,29.6862907 41,33) t=0 [0] (38.6568527,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
235SkOpSegment::markWinding id=2 (38.6568527,27.3431454 41,29.6862907 41,33) t=0 [1] (38.6568527,27.3431454) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
236SkOpSegment::nextChase mismatched signs
237SkOpSegment::markWinding id=3 (41,33 41,36.3137093 38.6568527,38.6568527) t=0 [0] (41,33) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
238SkOpSegment::markWinding id=3 (41,33 41,36.3137093 38.6568527,38.6568527) t=0 [1] (41,33) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
239SkOpSegment::markWinding id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [1] (27.3431454,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
240SkOpSegment::markWinding id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [0] (27.3431454,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
241SkOpSegment::markWinding id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [2] (27.3431454,27.3431454) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
242SkOpSegment::activeOp id=0 t=0 tEnd=1 op=union miFrom=1 miTo=0 suFrom=1 suTo=0 result=1
243SkOpSegment::nextChase mismatched signs
244SkOpSegment::findNextOp simple
245SkOpSegment::markDoneBinary id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [1] (27.3431454,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
246SkOpSegment::markDoneBinary id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [0] (27.3431454,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
247SkOpSegment::markDoneBinary id=0 (27.3431454,27.3431454 29.6862907,25 33,25) t=0 [2] (27.3431454,27.3431454) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
248bridgeOp current id=0 from=(27.3431454,27.3431454) to=(33,25)
249path.moveTo(27.3431454,27.3431454);
250path.quadTo(29.6862907,25, 33,25);
251SkOpSegment::nextChase mismatched signs
252SkOpSegment::findNextOp simple
253SkOpSegment::markDoneBinary id=1 (33,25 36.3137093,25 38.6568527,27.3431454) t=0 [0] (33,25) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
254SkOpSegment::markDoneBinary id=1 (33,25 36.3137093,25 38.6568527,27.3431454) t=0 [1] (33,25) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
255bridgeOp current id=1 from=(33,25) to=(38.6568527,27.3431454)
256path.quadTo(36.3137093,25, 38.6568527,27.3431454);
257SkOpSegment::nextChase mismatched signs
258SkOpSegment::findNextOp simple
259SkOpSegment::markDoneBinary id=2 (38.6568527,27.3431454 41,29.6862907 41,33) t=0 [0] (38.6568527,27.3431454) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
260SkOpSegment::markDoneBinary id=2 (38.6568527,27.3431454 41,29.6862907 41,33) t=0 [1] (38.6568527,27.3431454) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
261bridgeOp current id=2 from=(38.6568527,27.3431454) to=(41,33)
262path.quadTo(41,29.6862907, 41,33);
263SkOpSegment::markWinding id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 [0] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
264SkOpSegment::markWinding id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 [1] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
265SkOpSegment::markWinding id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 [2] (38.6568527,38.6568527) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
266SkOpSegment::markAngle last id=4 windSum=? small=0
267SkOpSegment::markWinding id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 [0] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
268SkOpSegment::markWinding id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 [1] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
269SkOpSegment::markWinding id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 [2] (38.6568527,38.6568527) tEnd=0.00258220891 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
270SkOpSegment::markAngle last id=21 windSum=? small=0
271SkOpSegment::findNextOp
272SkOpAngle::dumpOne [3/2] next=4/1 sect=1/5 s=1 [4] e=0 [1] sgn=1 windVal=1 windSum=-1 oppVal=1 oppSum=-1
273SkOpAngle::dumpOne [4/1] next=21/1 sect=18/17 s=0 [0] e=1 [3] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1
274SkOpAngle::dumpOne [21/1] next=3/2 sect=21/17 s=0 [0] e=0.00258220891 [3] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
275SkOpSegment::activeOp id=4 t=0 tEnd=1 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
276SkOpSegment::markDoneBinary id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 [0] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
277SkOpSegment::markDoneBinary id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 [1] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
278SkOpSegment::markDoneBinary id=4 (38.6568527,38.6568527 38.6510239,38.6626816 38.6447449,38.6689377) t=0 [2] (38.6568527,38.6568527) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
279SkOpSegment::findNextOp chase.append id=4 windSum=-2147483647 small=0
280SkOpSegment::activeOp id=21 t=0 tEnd=0.00258220891 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
281SkOpSegment::findNextOp chase.append id=21 windSum=-2147483647 small=0
282SkOpSegment::markDoneBinary id=3 (41,33 41,36.3137093 38.6568527,38.6568527) t=0 [0] (41,33) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
283SkOpSegment::markDoneBinary id=3 (41,33 41,36.3137093 38.6568527,38.6568527) t=0 [1] (41,33) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
284SkOpSegment::findNextOp from:[3] to:[21] start=0 end=3
285bridgeOp current id=3 from=(41,33) to=(38.6568527,38.6568527)
286path.quadTo(41,36.3137093, 38.6568527,38.6568527);
287SkOpSegment::findNextOp
288SkOpAngle::dumpOne [21/2] next=4/2 sect=1/1 s=0.00258220891 [3] e=0 [0] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
289SkOpAngle::dumpOne [4/2] next=18/1 sect=1/1 s=1 [6] e=0 [2] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 done
290SkOpAngle::dumpOne [18/1] next=5/1 sect=11/11 s=1 [4] e=0 [0] sgn=1 windVal=1 windSum=? done
291SkOpAngle::dumpOne [5/1] next=21/3 sect=21/21 s=0 [0] e=0.0149880862 [4] sgn=-1 windVal=1 windSum=? unorderable
292SkOpAngle::dumpOne [21/3] next=21/2 sect=21/21 s=0.00258220891 [3] e=0.0026162254 [7] sgn=-1 windVal=1 windSum=? oppVal=1 oppSum=? unorderable operand
293SkOpSegment::activeOp id=4 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
294SkOpSegment::activeOp id=18 t=1 tEnd=0 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
295SkOpSegment::activeOp id=5 t=0 tEnd=0.0149880862 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
296SkOpSegment::markDoneBinary id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0 [0] (38.6447449,38.6689377) tEnd=0 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=0
297SkOpSegment::markDoneBinary id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0 [1] (38.6447449,38.6689377) tEnd=0 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=0
298SkOpSegment::markDoneBinary id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0 [2] (38.6447449,38.6689377) tEnd=0 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=0
299SkOpSegment::markDoneBinary id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0 [3] (38.6447449,38.6689377) tEnd=0.0149880862 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=0
300SkOpSegment::activeOp id=21 t=0.00258220891 tEnd=0.0026162254 op=union miFrom=1 miTo=0 suFrom=1 suTo=0 result=1
301SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 [0] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
302SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 [1] (38.6568527,38.6568527) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
303SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0 [2] (38.6568527,38.6568527) tEnd=0.00258220891 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
304SkOpSegment::findNextOp from:[21] to:[21] start=3 end=7
305bridgeOp current id=21 from=(38.6568527,38.6568527) to=(38.6447449,38.6689377)
306path.quadTo(38.6510239,38.6626816, 38.6447449,38.6689377);
307SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00258220891 [3] (38.6447449,38.6689377) tEnd=0.00258220891 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=1
308SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00258220891 [4] (38.6447449,38.6689377) tEnd=0.00258220891 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=1
309SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00258220891 [5] (38.6447449,38.6689377) tEnd=0.00258220891 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=1
310SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00258220891 [6] (38.6447449,38.6689377) tEnd=0.0026162254 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=1
311SkOpSegment::debugShowActiveSpans id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0.0149880862 (38.6445847,38.6690979) tEnd=1 other=21 otherT=0.0026162254 otherIndex=7 windSum=? windValue=1 oppValue=0
312SkOpSegment::debugShowActiveSpans id=6 (38.6341171,38.6795731 38.6284409,38.6852493 38.6227531,38.6909218) t=0 (38.6341171,38.6795731) tEnd=1 other=5 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
313SkOpSegment::debugShowActiveSpans id=7 (38.6227531,38.6909218 36.2775421,41.0320053 32.9638329,41.0290833) t=0 (38.6227531,38.6909218) tEnd=1 other=6 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
314SkOpSegment::debugShowActiveSpans id=8 (32.9638329,41.0290833 29.6501274,41.0261612 27.3090477,38.6809464) t=0 (32.9638329,41.0290833) tEnd=1 other=7 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
315SkOpSegment::debugShowActiveSpans id=9 (27.3090477,38.6809464 24.9679718,36.3357391 24.9708939,33.0220299) t=0 (27.3090477,38.6809464) tEnd=1 other=8 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
316SkOpSegment::debugShowActiveSpans id=10 (24.9708939,33.0220299 24.973814,29.7083225 27.319025,27.3672428) t=0 (24.9708939,33.0220299) tEnd=1 other=9 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
317SkOpSegment::debugShowActiveSpans id=11 (27.319025,27.3672428 27.3209743,27.3652973 27.3229256,27.3633518) t=0 (27.319025,27.3672428) tEnd=1 other=10 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
318SkOpSegment::debugShowActiveSpans id=12 (27.3229256,27.3633518 27.324995,27.3612823 27.3270645,27.3592148) t=0 (27.3229256,27.3633518) tEnd=1 other=11 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
319SkOpSegment::debugShowActiveSpans id=13 (27.3270645,27.3592148 27.3312511,27.355032 27.3354416,27.3508568) t=0 (27.3270645,27.3592148) tEnd=1 other=12 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
320SkOpSegment::debugShowActiveSpans id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 (27.3354416,27.3508568) tEnd=1 other=24 otherT=0.998354892 otherIndex=5 windSum=? windValue=1 oppValue=-1
321SkOpSegment::debugShowActiveSpans id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0 (27.331131,27.3551788) tEnd=0.0266527086 other=24 otherT=0.99743327 otherIndex=1 windSum=? windValue=1 oppValue=0
322SkOpSegment::debugShowActiveSpans id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0.0266527086 (27.3314419,27.3548698) tEnd=1 other=24 otherT=0.997499486 otherIndex=3 windSum=? windValue=1 oppValue=0
323SkOpSegment::debugShowActiveSpans id=16 (27.3431988,27.3431988 27.3431454,27.3431454) t=0 (27.3431988,27.3431988) tEnd=1 other=15 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
324SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.0026162254 (38.6445847,38.6690979) tEnd=0.00362998223 other=5 otherT=0.0149880862 otherIndex=4 windSum=? windValue=1 oppValue=1
325SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00362998223 (38.6398277,38.6738319) tEnd=1 other=17 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
326SkOpSegment::debugShowActiveSpans id=22 (33,41 29.6862907,41 27.3431454,38.6568527) t=0 (33,41) tEnd=1 other=21 otherT=1 otherIndex=10 windSum=? windValue=1 oppValue=0
327SkOpSegment::debugShowActiveSpans id=23 (27.3431454,38.6568527 25,36.3137093 25,33) t=0 (27.3431454,38.6568527) tEnd=1 other=22 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
328SkOpSegment::debugShowActiveSpans id=24 (25,33 25,29.6862907 27.3431454,27.3431454) t=0.998354892 (27.3354416,27.3508568) tEnd=1 other=13 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
329SkOpSegment::debugShowActiveSpans id=17 (38.6398277,38.6738319 38.6447258,38.6689186) t=0 (38.6398277,38.6738319) tEnd=1 other=21 otherT=0.00362998223 otherIndex=8 windSum=? windValue=1 oppValue=0
330SkOpSegment::findTop
331SkOpAngle::dumpOne [0/1] next=24/2 sect=2/1 s=0 [0] e=1 [3] sgn=-1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 done
332SkOpAngle::dumpOne [24/2] next=16/1 sect=17/21 s=1 [8] e=0.998354892 [5] sgn=1 windVal=1 windSum=? operand stop
333SkOpAngle::dumpOne [16/1] next=0/1 sect=27/27 s=1 [3] e=0 [0] sgn=1 windVal=1 windSum=? stop
334SkOpSegment::markWinding id=16 (27.3431988,27.3431988 27.3431454,27.3431454) t=0 [0] (27.3431988,27.3431988) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
335SkOpSegment::markWinding id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0.0266527086 [2] (27.3314419,27.3548698) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
336SkOpSegment::nextChase mismatched signs
337SkOpSegment::markWinding id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0 [0] (27.331131,27.3551788) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
338SkOpSegment::markWinding id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0 [1] (27.331131,27.3551788) tEnd=0.0266527086 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
339SkOpSegment::nextChase mismatched signs
340SkOpSegment::markAngle last id=15 windSum=-1 small=0
341SkOpSegment::markWinding id=24 (25,33 25,29.6862907 27.3431454,27.3431454) t=0.998354892 [4] (27.3354416,27.3508568) tEnd=0.998354892 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
342SkOpSegment::markWinding id=24 (25,33 25,29.6862907 27.3431454,27.3431454) t=0.998354892 [5] (27.3354416,27.3508568) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
343SkOpSegment::markAngle last id=24 windSum=-1 small=0
344SkOpSegment::activeOp id=24 t=0.998354892 tEnd=1 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
345SkOpSegment::findNextOp
346SkOpAngle::dumpOne [24/2] next=16/1 sect=17/21 s=1 [8] e=0.998354892 [5] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand stop
347SkOpAngle::dumpOne [16/1] next=0/1 sect=27/27 s=1 [3] e=0 [0] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 stop
348SkOpAngle::dumpOne [0/1] next=24/2 sect=2/1 s=0 [0] e=1 [3] sgn=-1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 done
349SkOpSegment::activeOp id=16 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
350SkOpSegment::markDoneBinary id=16 (27.3431988,27.3431988 27.3431454,27.3431454) t=0 [0] (27.3431988,27.3431988) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
351SkOpSegment::markDoneBinary id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0.0266527086 [2] (27.3314419,27.3548698) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
352SkOpSegment::nextChase mismatched signs
353SkOpSegment::markDoneBinary id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0 [0] (27.331131,27.3551788) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
354SkOpSegment::markDoneBinary id=15 (27.331131,27.3551788 27.3369579,27.3493824 27.3431988,27.3431988) t=0 [1] (27.331131,27.3551788) tEnd=0.0266527086 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
355SkOpSegment::nextChase mismatched signs
356SkOpSegment::findNextOp chase.append id=15 windSum=-1 small=0
357SkOpSegment::activeOp id=0 t=0 tEnd=1 op=union miFrom=1 miTo=0 suFrom=1 suTo=0 result=1
358SkOpSegment::markDoneBinary id=24 (25,33 25,29.6862907 27.3431454,27.3431454) t=0.998354892 [4] (27.3354416,27.3508568) tEnd=0.998354892 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
359SkOpSegment::markDoneBinary id=24 (25,33 25,29.6862907 27.3431454,27.3431454) t=0.998354892 [5] (27.3354416,27.3508568) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
360SkOpSegment::findNextOp from:[24] to:[0] start=0 end=3
361bridgeOp current id=24 from=(27.3354416,27.3508568) to=(27.3431454,27.3431454)
362path.moveTo(27.3354416,27.3508568);
363path.quadTo(27.3392906,27.3470001, 27.3431454,27.3431454);
364SkOpSegment::markWinding id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 [0] (27.3354416,27.3508568) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=-1
365SkOpSegment::markWinding id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 [1] (27.3354416,27.3508568) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=-1
366SkOpSegment::markAngle last id=14 windSum=-1 small=0
367SkOpSegment::debugShowActiveSpans id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0.0149880862 (38.6445847,38.6690979) tEnd=1 other=21 otherT=0.0026162254 otherIndex=7 windSum=? windValue=1 oppValue=0
368SkOpSegment::debugShowActiveSpans id=6 (38.6341171,38.6795731 38.6284409,38.6852493 38.6227531,38.6909218) t=0 (38.6341171,38.6795731) tEnd=1 other=5 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
369SkOpSegment::debugShowActiveSpans id=7 (38.6227531,38.6909218 36.2775421,41.0320053 32.9638329,41.0290833) t=0 (38.6227531,38.6909218) tEnd=1 other=6 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
370SkOpSegment::debugShowActiveSpans id=8 (32.9638329,41.0290833 29.6501274,41.0261612 27.3090477,38.6809464) t=0 (32.9638329,41.0290833) tEnd=1 other=7 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
371SkOpSegment::debugShowActiveSpans id=9 (27.3090477,38.6809464 24.9679718,36.3357391 24.9708939,33.0220299) t=0 (27.3090477,38.6809464) tEnd=1 other=8 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
372SkOpSegment::debugShowActiveSpans id=10 (24.9708939,33.0220299 24.973814,29.7083225 27.319025,27.3672428) t=0 (24.9708939,33.0220299) tEnd=1 other=9 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
373SkOpSegment::debugShowActiveSpans id=11 (27.319025,27.3672428 27.3209743,27.3652973 27.3229256,27.3633518) t=0 (27.319025,27.3672428) tEnd=1 other=10 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
374SkOpSegment::debugShowActiveSpans id=12 (27.3229256,27.3633518 27.324995,27.3612823 27.3270645,27.3592148) t=0 (27.3229256,27.3633518) tEnd=1 other=11 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
375SkOpSegment::debugShowActiveSpans id=13 (27.3270645,27.3592148 27.3312511,27.355032 27.3354416,27.3508568) t=0 (27.3270645,27.3592148) tEnd=1 other=12 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
376SkOpSegment::debugShowActiveSpans id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 (27.3354416,27.3508568) tEnd=1 other=24 otherT=0.998354892 otherIndex=5 windSum=-1 windValue=1 oppValue=-1
377SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.0026162254 (38.6445847,38.6690979) tEnd=0.00362998223 other=5 otherT=0.0149880862 otherIndex=4 windSum=? windValue=1 oppValue=1
378SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00362998223 (38.6398277,38.6738319) tEnd=1 other=17 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
379SkOpSegment::debugShowActiveSpans id=22 (33,41 29.6862907,41 27.3431454,38.6568527) t=0 (33,41) tEnd=1 other=21 otherT=1 otherIndex=10 windSum=? windValue=1 oppValue=0
380SkOpSegment::debugShowActiveSpans id=23 (27.3431454,38.6568527 25,36.3137093 25,33) t=0 (27.3431454,38.6568527) tEnd=1 other=22 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
381SkOpSegment::debugShowActiveSpans id=17 (38.6398277,38.6738319 38.6447258,38.6689186) t=0 (38.6398277,38.6738319) tEnd=1 other=21 otherT=0.00362998223 otherIndex=8 windSum=? windValue=1 oppValue=0
382SkOpSegment::activeOp id=14 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=1 suTo=0 result=0
383SkOpSegment::markDoneBinary id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 [0] (27.3354416,27.3508568) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=-1
384SkOpSegment::markDoneBinary id=14 (27.3354416,27.3508568 27.3332844,27.3530178 27.331131,27.3551788) t=0 [1] (27.3354416,27.3508568) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=-1
385bridgeOp chase.append id=14 windSum=-1 small=0
386SkOpSegment::markWinding id=13 (27.3270645,27.3592148 27.3312511,27.355032 27.3354416,27.3508568) t=0 [0] (27.3270645,27.3592148) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
387SkOpSegment::markWinding id=12 (27.3229256,27.3633518 27.324995,27.3612823 27.3270645,27.3592148) t=0 [0] (27.3229256,27.3633518) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
388SkOpSegment::markWinding id=11 (27.319025,27.3672428 27.3209743,27.3652973 27.3229256,27.3633518) t=0 [0] (27.319025,27.3672428) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
389SkOpSegment::markWinding id=10 (24.9708939,33.0220299 24.973814,29.7083225 27.319025,27.3672428) t=0 [0] (24.9708939,33.0220299) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
390SkOpSegment::markWinding id=9 (27.3090477,38.6809464 24.9679718,36.3357391 24.9708939,33.0220299) t=0 [0] (27.3090477,38.6809464) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
391SkOpSegment::markWinding id=8 (32.9638329,41.0290833 29.6501274,41.0261612 27.3090477,38.6809464) t=0 [0] (32.9638329,41.0290833) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
392SkOpSegment::markWinding id=7 (38.6227531,38.6909218 36.2775421,41.0320053 32.9638329,41.0290833) t=0 [0] (38.6227531,38.6909218) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
393SkOpSegment::markWinding id=6 (38.6341171,38.6795731 38.6284409,38.6852493 38.6227531,38.6909218) t=0 [0] (38.6341171,38.6795731) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
394SkOpSegment::markWinding id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0.0149880862 [4] (38.6445847,38.6690979) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
395SkOpSegment::markAngle last id=5 windSum=-1 small=0
396SkOpSegment::debugShowActiveSpans id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0.0149880862 (38.6445847,38.6690979) tEnd=1 other=21 otherT=0.0026162254 otherIndex=7 windSum=-1 windValue=1 oppValue=0
397SkOpSegment::debugShowActiveSpans id=6 (38.6341171,38.6795731 38.6284409,38.6852493 38.6227531,38.6909218) t=0 (38.6341171,38.6795731) tEnd=1 other=5 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
398SkOpSegment::debugShowActiveSpans id=7 (38.6227531,38.6909218 36.2775421,41.0320053 32.9638329,41.0290833) t=0 (38.6227531,38.6909218) tEnd=1 other=6 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
399SkOpSegment::debugShowActiveSpans id=8 (32.9638329,41.0290833 29.6501274,41.0261612 27.3090477,38.6809464) t=0 (32.9638329,41.0290833) tEnd=1 other=7 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
400SkOpSegment::debugShowActiveSpans id=9 (27.3090477,38.6809464 24.9679718,36.3357391 24.9708939,33.0220299) t=0 (27.3090477,38.6809464) tEnd=1 other=8 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
401SkOpSegment::debugShowActiveSpans id=10 (24.9708939,33.0220299 24.973814,29.7083225 27.319025,27.3672428) t=0 (24.9708939,33.0220299) tEnd=1 other=9 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
402SkOpSegment::debugShowActiveSpans id=11 (27.319025,27.3672428 27.3209743,27.3652973 27.3229256,27.3633518) t=0 (27.319025,27.3672428) tEnd=1 other=10 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
403SkOpSegment::debugShowActiveSpans id=12 (27.3229256,27.3633518 27.324995,27.3612823 27.3270645,27.3592148) t=0 (27.3229256,27.3633518) tEnd=1 other=11 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
404SkOpSegment::debugShowActiveSpans id=13 (27.3270645,27.3592148 27.3312511,27.355032 27.3354416,27.3508568) t=0 (27.3270645,27.3592148) tEnd=1 other=12 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
405SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.0026162254 (38.6445847,38.6690979) tEnd=0.00362998223 other=5 otherT=0.0149880862 otherIndex=4 windSum=? windValue=1 oppValue=1
406SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00362998223 (38.6398277,38.6738319) tEnd=1 other=17 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
407SkOpSegment::debugShowActiveSpans id=22 (33,41 29.6862907,41 27.3431454,38.6568527) t=0 (33,41) tEnd=1 other=21 otherT=1 otherIndex=10 windSum=? windValue=1 oppValue=0
408SkOpSegment::debugShowActiveSpans id=23 (27.3431454,38.6568527 25,36.3137093 25,33) t=0 (27.3431454,38.6568527) tEnd=1 other=22 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
409SkOpSegment::debugShowActiveSpans id=17 (38.6398277,38.6738319 38.6447258,38.6689186) t=0 (38.6398277,38.6738319) tEnd=1 other=21 otherT=0.00362998223 otherIndex=8 windSum=? windValue=1 oppValue=0
410SkOpSegment::activeOp id=13 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
411SkOpSegment::findNextOp simple
412SkOpSegment::markDoneBinary id=13 (27.3270645,27.3592148 27.3312511,27.355032 27.3354416,27.3508568) t=0 [0] (27.3270645,27.3592148) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
413bridgeOp current id=13 from=(27.3354416,27.3508568) to=(27.3270645,27.3592148)
414path.moveTo(27.3354416,27.3508568);
415path.quadTo(27.3312511,27.355032, 27.3270645,27.3592148);
416SkOpSegment::findNextOp simple
417SkOpSegment::markDoneBinary id=12 (27.3229256,27.3633518 27.324995,27.3612823 27.3270645,27.3592148) t=0 [0] (27.3229256,27.3633518) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
418bridgeOp current id=12 from=(27.3270645,27.3592148) to=(27.3229256,27.3633518)
419path.quadTo(27.324995,27.3612823, 27.3229256,27.3633518);
420SkOpSegment::findNextOp simple
421SkOpSegment::markDoneBinary id=11 (27.319025,27.3672428 27.3209743,27.3652973 27.3229256,27.3633518) t=0 [0] (27.319025,27.3672428) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
422bridgeOp current id=11 from=(27.3229256,27.3633518) to=(27.319025,27.3672428)
423path.quadTo(27.3209743,27.3652973, 27.319025,27.3672428);
424SkOpSegment::findNextOp simple
425SkOpSegment::markDoneBinary id=10 (24.9708939,33.0220299 24.973814,29.7083225 27.319025,27.3672428) t=0 [0] (24.9708939,33.0220299) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
426bridgeOp current id=10 from=(27.319025,27.3672428) to=(24.9708939,33.0220299)
427path.quadTo(24.973814,29.7083225, 24.9708939,33.0220299);
428SkOpSegment::findNextOp simple
429SkOpSegment::markDoneBinary id=9 (27.3090477,38.6809464 24.9679718,36.3357391 24.9708939,33.0220299) t=0 [0] (27.3090477,38.6809464) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
430bridgeOp current id=9 from=(24.9708939,33.0220299) to=(27.3090477,38.6809464)
431path.quadTo(24.9679718,36.3357391, 27.3090477,38.6809464);
432SkOpSegment::findNextOp simple
433SkOpSegment::markDoneBinary id=8 (32.9638329,41.0290833 29.6501274,41.0261612 27.3090477,38.6809464) t=0 [0] (32.9638329,41.0290833) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
434bridgeOp current id=8 from=(27.3090477,38.6809464) to=(32.9638329,41.0290833)
435path.quadTo(29.6501274,41.0261612, 32.9638329,41.0290833);
436SkOpSegment::findNextOp simple
437SkOpSegment::markDoneBinary id=7 (38.6227531,38.6909218 36.2775421,41.0320053 32.9638329,41.0290833) t=0 [0] (38.6227531,38.6909218) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
438bridgeOp current id=7 from=(32.9638329,41.0290833) to=(38.6227531,38.6909218)
439path.quadTo(36.2775421,41.0320053, 38.6227531,38.6909218);
440SkOpSegment::findNextOp simple
441SkOpSegment::markDoneBinary id=6 (38.6341171,38.6795731 38.6284409,38.6852493 38.6227531,38.6909218) t=0 [0] (38.6341171,38.6795731) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
442bridgeOp current id=6 from=(38.6227531,38.6909218) to=(38.6341171,38.6795731)
443path.quadTo(38.6284409,38.6852493, 38.6341171,38.6795731);
444SkOpSegment::findNextOp
445SkOpAngle::dumpOne [5/3] next=5/2 sect=21/21 s=0.0149880862 [4] e=1 [5] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
446SkOpAngle::dumpOne [5/2] next=21/4 sect=1/1 s=0.0149880862 [4] e=0 [0] sgn=1 windVal=1 windSum=? done unorderable
447SkOpAngle::dumpOne [21/4] next=21/5 sect=1/1 s=0.0026162254 [7] e=0.00258220891 [3] sgn=1 windVal=1 windSum=? oppVal=1 oppSum=? done unorderable operand
448SkOpAngle::dumpOne [21/5] next=5/3 sect=17/17 s=0.0026162254 [7] e=0.00362998223 [8] sgn=-1 windVal=1 windSum=? oppVal=1 oppSum=? operand
449SkOpSegment::activeOp id=5 t=0.0149880862 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
450SkOpSegment::activeOp id=21 t=0.0026162254 tEnd=0.00258220891 op=union miFrom=1 miTo=0 suFrom=0 suTo=1 result=0
451SkOpSegment::activeOp id=21 t=0.0026162254 tEnd=0.00362998223 op=union miFrom=0 miTo=1 suFrom=1 suTo=0 result=0
452SkOpSegment::markDoneBinary id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.0026162254 [7] (38.6445847,38.6690979) tEnd=0.00362998223 newWindSum=-2147483647 newOppSum=-2147483647 oppSum=? windSum=? windValue=1 oppValue=1
453SkOpSegment::markDoneBinary id=5 (38.6447449,38.6689377 38.6394348,38.6742554 38.6341171,38.6795731) t=0.0149880862 [4] (38.6445847,38.6690979) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
454SkOpSegment::findNextOp from:[5] to:[5] start=4 end=0
455bridgeOp current id=5 from=(38.6341171,38.6795731) to=(38.6445847,38.6690979)
456path.quadTo(38.6393547,38.6743355, 38.6445847,38.6690979);
457SkOpSegment::debugShowActiveSpans id=21 (38.6568527,38.6568527 36.3137093,41 33,41) t=0.00362998223 (38.6398277,38.6738319) tEnd=1 other=17 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
458SkOpSegment::debugShowActiveSpans id=22 (33,41 29.6862907,41 27.3431454,38.6568527) t=0 (33,41) tEnd=1 other=21 otherT=1 otherIndex=10 windSum=? windValue=1 oppValue=0
459SkOpSegment::debugShowActiveSpans id=23 (27.3431454,38.6568527 25,36.3137093 25,33) t=0 (27.3431454,38.6568527) tEnd=1 other=22 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
460SkOpSegment::debugShowActiveSpans id=17 (38.6398277,38.6738319 38.6447258,38.6689186) t=0 (38.6398277,38.6738319) tEnd=1 other=21 otherT=0.00362998223 otherIndex=8 windSum=? windValue=1 oppValue=0
461d:\cygwin\puregit\src\pathops\skopsegment.cpp:472: failed assertion "span.fT > 0"
caryclarkdac1d172014-06-17 05:15:38 -0700462</div>
caryclarkdac1d172014-06-17 05:15:38 -0700463</div>
464
465<script type="text/javascript">
466
467var testDivs = [
caryclark65f55312014-11-13 06:58:52 -0800468 fuzz763_1026368,
caryclarkdac1d172014-06-17 05:15:38 -0700469];
470
471var decimal_places = 3; // make this 3 to show more precision
472
473var tests = [];
474var testLines = [];
475var testTitles = [];
476var testIndex = 0;
477var ctx;
478
479var xmin, xmax, focusXmin, focusXmax;
480var ymin, ymax, focusYmin, focusYmax;
481var scale;
482var mouseX, mouseY;
483var srcLeft, srcTop;
484var screenWidth, screenHeight;
485var drawnPts, drawnLines, drawnQuads, drawnCubics;
486var curveT = 0;
487
488var pt_labels = 2;
489var collect_bounds = false;
490var control_lines = 0;
491var curve_t = false;
492var debug_xy = 1;
493var focus_enabled = false;
494var focus_on_selection = false;
495var step_limit = 0;
496var draw_active = false;
497var draw_add = false;
498var draw_angle = 0;
499var draw_deriviatives = 0;
500var draw_hints = false;
501var draw_hodo = 0;
502var draw_id = false;
503var draw_intersection = 0;
504var draw_intersectT = false;
505var draw_legend = true;
506var draw_log = false;
507var draw_mark = false;
508var draw_midpoint = false;
509var draw_op = 0;
510var draw_sequence = false;
511var draw_sort = 0;
512var draw_path = 3;
513var draw_computed = 0;
514var retina_scale = !!window.devicePixelRatio;
515
516var activeCount = 0;
517var addCount = 0;
518var angleCount = 0;
519var opCount = 0;
520var sectCount = 0;
521var sortCount = 0;
522var markCount = 0;
523var activeMax = 0;
524var addMax = 0;
525var angleMax = 0;
526var sectMax = 0;
527var sectMax2 = 0;
528var sortMax = 0;
529var markMax = 0;
530var opMax = 0;
531var stepMax = 0;
532var lastIndex = 0;
533var hasPath = false;
534var hasComputedPath = false;
535
536var firstActiveSpan = -1;
537var logStart = -1;
538var logRange = 0;
539
540var SPAN_ID = 0;
541var SPAN_X1 = SPAN_ID + 1;
542var SPAN_Y1 = SPAN_X1 + 1;
543var SPAN_X2 = SPAN_Y1 + 1;
544var SPAN_Y2 = SPAN_X2 + 1;
545var SPAN_L_T = SPAN_Y2 + 1;
546var SPAN_L_TX = SPAN_L_T + 1;
547var SPAN_L_TY = SPAN_L_TX + 1;
548var SPAN_L_TEND = SPAN_L_TY + 1;
549var SPAN_L_OTHER = SPAN_L_TEND + 1;
550var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
551var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
552var SPAN_L_SUM = SPAN_L_OTHERI + 1;
553var SPAN_L_VAL = SPAN_L_SUM + 1;
554var SPAN_L_OPP = SPAN_L_VAL + 1;
555
556var SPAN_X3 = SPAN_Y2 + 1;
557var SPAN_Y3 = SPAN_X3 + 1;
558var SPAN_Q_T = SPAN_Y3 + 1;
559var SPAN_Q_TX = SPAN_Q_T + 1;
560var SPAN_Q_TY = SPAN_Q_TX + 1;
561var SPAN_Q_TEND = SPAN_Q_TY + 1;
562var SPAN_Q_OTHER = SPAN_Q_TEND + 1;
563var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
564var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
565var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
566var SPAN_Q_VAL = SPAN_Q_SUM + 1;
567var SPAN_Q_OPP = SPAN_Q_VAL + 1;
568
569var SPAN_X4 = SPAN_Y3 + 1;
570var SPAN_Y4 = SPAN_X4 + 1;
571var SPAN_C_T = SPAN_Y4 + 1;
572var SPAN_C_TX = SPAN_C_T + 1;
573var SPAN_C_TY = SPAN_C_TX + 1;
574var SPAN_C_TEND = SPAN_C_TY + 1;
575var SPAN_C_OTHER = SPAN_C_TEND + 1;
576var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
577var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
578var SPAN_C_SUM = SPAN_C_OTHERI + 1;
579var SPAN_C_VAL = SPAN_C_SUM + 1;
580var SPAN_C_OPP = SPAN_C_VAL + 1;
581
582var ACTIVE_LINE_SPAN = 1;
583var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
584var ACTIVE_CUBIC_SPAN = ACTIVE_QUAD_SPAN + 1;
585
586var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
587var ADD_LINETO = ADD_MOVETO + 1;
588var ADD_QUADTO = ADD_LINETO + 1;
589var ADD_CUBICTO = ADD_QUADTO + 1;
590var ADD_CLOSE = ADD_CUBICTO + 1;
591var ADD_FILL = ADD_CLOSE + 1;
592
593var PATH_LINE = ADD_FILL + 1;
594var PATH_QUAD = PATH_LINE + 1;
595var PATH_CUBIC = PATH_QUAD + 1;
596
597var INTERSECT_LINE = PATH_CUBIC + 1;
598var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
599var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
600var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
601var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
602var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
603var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
604var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
605var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
606var INTERSECT_SELF_CUBIC = INTERSECT_QUAD_NO + 1;
607var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
608var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
609var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
610var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
611var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
612var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
613var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
614var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
615var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
616var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
617var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
618var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
619var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
620var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
621// FIXME: add cubic 5- 9
622var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
623
624var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
625var SORT_BINARY = SORT_UNARY + 1;
626
627var OP_DIFFERENCE = SORT_BINARY + 1;
628var OP_INTERSECT = OP_DIFFERENCE + 1;
629var OP_UNION = OP_INTERSECT + 1;
630var OP_XOR = OP_UNION + 1;
631
632var MARK_LINE = OP_XOR + 1;
633var MARK_QUAD = MARK_LINE + 1;
634var MARK_CUBIC = MARK_QUAD + 1;
635var MARK_DONE_LINE = MARK_CUBIC + 1;
636var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
637var MARK_DONE_CUBIC = MARK_DONE_QUAD + 1;
638var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
639var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
640var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_QUAD + 1;
641var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
642var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
643var MARK_SIMPLE_CUBIC = MARK_SIMPLE_QUAD + 1;
644var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
645var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
646var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_QUAD + 1;
647var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
648var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
649var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_QUAD + 1;
650var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
651
652var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
653var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
654
655var ANGLE_AFTER = COMPUTED_SET_2;
656var ANGLE_AFTER2 = ANGLE_AFTER + 1;
657
658var ACTIVE_OP = ANGLE_AFTER2 + 1;
659
660var FRAG_TYPE_LAST = ACTIVE_OP;
661
662var REC_TYPE_UNKNOWN = -1;
663var REC_TYPE_PATH = 0;
664var REC_TYPE_SECT = 1;
665var REC_TYPE_ACTIVE = 2;
666var REC_TYPE_ADD = 3;
667var REC_TYPE_SORT = 4;
668var REC_TYPE_OP = 5;
669var REC_TYPE_MARK = 6;
670var REC_TYPE_COMPUTED = 7;
671var REC_TYPE_COIN = 8;
672var REC_TYPE_ANGLE = 9;
673var REC_TYPE_ACTIVE_OP = 10;
674var REC_TYPE_LAST = REC_TYPE_ACTIVE_OP;
675
676function strs_to_nums(strs) {
677 var result = [];
678 for (var idx = 1; idx < strs.length; ++idx) {
679 var str = strs[idx];
680 var num = parseFloat(str);
681 if (isNaN(num)) {
682 result.push(str);
683 } else {
684 result.push(num);
685 }
686 }
687 return result;
688}
689
690function filter_str_by(id, str, regex, array) {
691 if (regex.test(str)) {
692 var strs = regex.exec(str);
693 var result = strs_to_nums(strs);
694 array.push(id);
695 array.push(result);
696 return true;
697 }
698 return false;
699}
700
701function construct_regexp2(pattern) {
702 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
703 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
704 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
705 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
706 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
707 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
708 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
709 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
710 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
711 escape = escape.replace(/PATH/g, "pathB?");
712 escape = escape.replace(/IDX/g, "(\\d+)");
713 escape = escape.replace(/NUM/g, "(-?\\d+)");
714 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
715 return new RegExp(escape, 'i');
716}
717
718function construct_regexp2c(pattern) {
719 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
720 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
721 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}");
722 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}");
723 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{P_VAL\\}, \\{P_VAL\\}\\}");
724 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
725 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
726 escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?,(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
727 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
728 escape = escape.replace(/OPER/g, "[a-z]+");
729 escape = escape.replace(/PATH/g, "pathB?");
730 escape = escape.replace(/T_F/g, "([TF])");
731 escape = escape.replace(/IDX/g, "(\\d+)");
732 escape = escape.replace(/NUM/g, "(-?\\d+)");
733 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
734 return new RegExp(escape, 'i');
735}
736
737function match_regexp(str, lineNo, array, id, pattern) {
738 var regex = construct_regexp2(pattern);
739 if (filter_str_by(id, str, regex, array)) {
740 return true;
741 }
742 regex = construct_regexp2c(pattern);
743 return filter_str_by(id, str, regex, array);
744}
745
746function endsWith(str, suffix) {
747 return str.indexOf(suffix, str.length - suffix.length) !== -1;
748}
749
750function parse_all(test) {
751 var lines = test.match(/[^\r\n]+/g);
752 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
753 var record = [];
754 var recType = REC_TYPE_UNKNOWN;
755 var lastLineNo;
756 var moveX, moveY;
757 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
758 var line = lines[lineNo];
759 if (line.length == 0) {
760 continue;
761 }
762 var opStart = "SkOpSegment::";
763 if (line.lastIndexOf(opStart, 0) === 0) {
764 line = line.substr(opStart.length);
765 }
766 var angleStart = "SkOpAngle::";
767 if (line.lastIndexOf(angleStart, 0) === 0) {
768 line = line.substr(angleStart.length);
769 }
770 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
771 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
772 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
773 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
774 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
775 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
776 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
777 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
778 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
779 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
780 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
781 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
782 : line.lastIndexOf("{{", 0) === 0 ? REC_TYPE_PATH
783 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
784 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
785 : REC_TYPE_UNKNOWN;
786 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
787 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
788 if (recType != REC_TYPE_UNKNOWN) {
789 records.push(recType);
790 records.push(lastLineNo);
791 records.push(record);
792 }
793 record = [];
794 recType = type;
795 lastLineNo = lineNo;
796 }
797 var found = false;
798 switch (recType) {
799 case REC_TYPE_ACTIVE:
800 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
801" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL other=IDX otherT=T_VAL otherIndex=IDX windSum=OPT windValue=IDX oppValue=NUM"
802 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
803" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL other=IDX otherT=T_VAL otherIndex=IDX windSum=OPT windValue=IDX oppValue=NUM"
804 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
805" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL other=IDX otherT=T_VAL otherIndex=IDX windSum=OPT windValue=IDX oppValue=NUM"
806 );
807 break;
808 case REC_TYPE_ACTIVE_OP:
809 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
810" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
811 );
812 break;
813 case REC_TYPE_ADD:
814 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
815 moveX = record[1][0];
816 moveY = record[1][1];
817 found = true;
818 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
819 record[1].unshift(moveY);
820 record[1].unshift(moveX);
821 moveX = record[1][2];
822 moveY = record[1][3];
823 found = true;
824 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
825 record[1].unshift(moveY);
826 record[1].unshift(moveX);
827 moveX = record[1][4];
828 moveY = record[1][5];
829 found = true;
830 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
831 record[1].unshift(moveY);
832 record[1].unshift(moveX);
833 moveX = record[1][6];
834 moveY = record[1][7];
835 found = true;
836 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
837 found = true;
838 } else {
839 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
840 }
841 break;
842 case REC_TYPE_ANGLE:
843 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
844"id=IDX IDX/IDX tStart=T_VAL tEnd=T_VAL < id=IDX IDX/IDX tStart=T_VAL tEnd=T_VAL < id=IDX IDX/IDX tStart=T_VAL tEnd=T_VAL T_F IDX");
845 if (found) {
846 break;
847 }
848 found = match_regexp(line, lineNo, record, ANGLE_AFTER2, "after " +
849"[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");
850 break;
851 case REC_TYPE_COIN:
852 found = true;
853 break;
854 case REC_TYPE_COMPUTED:
855 found = line == "computed quadratics given"
856 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
857 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
858 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
859 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
860 );
861 break;
862 case REC_TYPE_PATH:
863 found = match_regexp(line, lineNo, record, PATH_LINE, "LINE_VAL"
864 ) || match_regexp(line, lineNo, record, PATH_QUAD, "QUAD_VAL"
865 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "CUBIC_VAL"
866 );
867 break;
868 case REC_TYPE_SECT:
869 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
870" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
871 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
872" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
873 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
874" no intersect LINE_VAL LINE_VAL"
875 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
876" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
877 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
878" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
879 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
880" no intersect QUAD_VAL LINE_VAL"
881 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
882" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
883 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
884" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
885 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
886" no intersect QUAD_VAL QUAD_VAL"
887 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
888" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
889 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
890" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
891 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
892" 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"
893 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
894" no intersect CUBIC_VAL LINE_VAL"
895 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
896" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
897 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
898" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
899 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
900" 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"
901 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
902" 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"
903 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
904" no intersect CUBIC_VAL QUAD_VAL"
905 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
906" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
907 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
908" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
909 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
910" 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"
911 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
912" 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"
913 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
914" no intersect CUBIC_VAL CUBIC_VAL"
915 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
916" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
917 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
918" no self intersect CUBIC_VAL"
919 );
920 break;
921 case REC_TYPE_SORT:
922 var hasDone = / done/.test(line);
923 var hasUnorderable = / unorderable/.test(line);
924 var hasSmall = / small/.test(line);
925 var hasTiny = / tiny/.test(line);
926 var hasOperand = / operand/.test(line);
927 var hasStop = / stop/.test(line);
928 line.replace(/[ a-z]+$/, "");
929 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
930" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
931 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
932" [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"
933 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
934" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
935 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
936" [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"
937 );
938 if (found) {
939 record[1].push(hasDone);
940 record[1].push(hasUnorderable);
941 record[1].push(hasSmall);
942 record[1].push(hasTiny);
943 record[1].push(hasOperand);
944 record[1].push(hasStop);
945 }
946 break;
947 case REC_TYPE_MARK:
948 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
949" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
950 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
951" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
952 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
953" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
954 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDoneBinary" +
955" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
956 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDoneBinary" +
957" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
958 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDoneBinary" +
959" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
960 ) || match_regexp(line, lineNo, record, MARK_UNSORTABLE_LINE, "markUnsortable" +
961" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
962 ) || match_regexp(line, lineNo, record, MARK_UNSORTABLE_QUAD, "markUnsortable" +
963" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
964 ) || match_regexp(line, lineNo, record, MARK_UNSORTABLE_CUBIC, "markUnsortable" +
965" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
966 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
967" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
968 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
969" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
970 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
971" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
972 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_DONE_LINE, "markDone" +
973" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
974 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_DONE_QUAD, "markDone" +
975" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
976 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_DONE_CUBIC, "markDone" +
977" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
978 ) || match_regexp(line, lineNo, record, MARK_DONE_UNARY_LINE, "markDoneUnary" +
979" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
980 ) || match_regexp(line, lineNo, record, MARK_DONE_UNARY_QUAD, "markDoneUnary" +
981" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
982 ) || match_regexp(line, lineNo, record, MARK_DONE_UNARY_CUBIC, "markDoneUnary" +
983" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
984 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
985" last id=IDX windSum=OPT small=IDX");
986 break;
987 case REC_TYPE_OP:
988 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
989 || line.lastIndexOf("operator<", 0) === 0) {
990 found = true;
991 break;
992 }
993 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op difference"
994 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
995 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
996 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
997 );
998 break;
999 case REC_TYPE_UNKNOWN:
1000 found = true;
1001 break;
1002 }
1003 if (!found) {
1004 console.log(line + " [" + lineNo + "] of type " + type + " not found");
1005 }
1006 }
1007 if (recType != REC_TYPE_UNKNOWN) {
1008 records.push(recType);
1009 records.push(lastLineNo);
1010 records.push(record);
1011 }
1012 if (records.length >= 1) {
1013 tests[testIndex] = records;
1014 testLines[testIndex] = lines;
1015 }
1016}
1017
1018function init(test) {
1019 var canvas = document.getElementById('canvas');
1020 if (!canvas.getContext) return;
1021 ctx = canvas.getContext('2d');
1022 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
1023 var unscaledWidth = window.innerWidth - 20;
1024 var unscaledHeight = window.innerHeight - 20;
1025 screenWidth = unscaledWidth;
1026 screenHeight = unscaledHeight;
1027 canvas.width = unscaledWidth * resScale;
1028 canvas.height = unscaledHeight * resScale;
1029 canvas.style.width = unscaledWidth + 'px';
1030 canvas.style.height = unscaledHeight + 'px';
1031 if (resScale != 1) {
1032 ctx.scale(resScale, resScale);
1033 }
1034 xmin = Infinity;
1035 xmax = -Infinity;
1036 ymin = Infinity;
1037 ymax = -Infinity;
1038 hasPath = hasComputedPath = false;
1039 firstActiveSpan = -1;
1040 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1041 var recType = test[tIndex];
1042 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
1043 console.log("unknown rec type: " + recType);
1044 throw "stop execution";
1045 }
1046 var records = test[tIndex + 2];
1047 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1048 var fragType = records[recordIndex];
1049 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
1050 console.log("unknown in range frag type: " + fragType);
1051 throw "stop execution";
1052 }
1053 var frags = records[recordIndex + 1];
1054 var first = 0;
1055 var last = -1;
1056 var first2 = 0;
1057 var last2 = 0;
1058 switch (recType) {
1059 case REC_TYPE_COMPUTED:
1060 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
1061 break;
1062 }
1063 hasComputedPath = true;
1064 case REC_TYPE_PATH:
1065 switch (fragType) {
1066 case PATH_LINE:
1067 last = 4;
1068 break;
1069 case PATH_QUAD:
1070 last = 6;
1071 break;
1072 case PATH_CUBIC:
1073 last = 8;
1074 break;
1075 default:
1076 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
1077 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1078 throw "stop execution";
1079 }
1080 if (recType == REC_TYPE_PATH) {
1081 hasPath = true;
1082 }
1083 break;
1084 case REC_TYPE_ACTIVE:
1085 if (firstActiveSpan < 0) {
1086 firstActiveSpan = tIndex;
1087 }
1088 first = 1;
1089 switch (fragType) {
1090 case ACTIVE_LINE_SPAN:
1091 last = 5;
1092 break;
1093 case ACTIVE_QUAD_SPAN:
1094 last = 7;
1095 break;
1096 case ACTIVE_CUBIC_SPAN:
1097 last = 9;
1098 break;
1099 default:
1100 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1101 throw "stop execution";
1102 }
1103 break;
1104 case REC_TYPE_ADD:
1105 switch (fragType) {
1106 case ADD_MOVETO:
1107 break;
1108 case ADD_LINETO:
1109 last = 4;
1110 break;
1111 case ADD_QUADTO:
1112 last = 6;
1113 break;
1114 case ADD_CUBICTO:
1115 last = 8;
1116 break;
1117 case ADD_CLOSE:
1118 case ADD_FILL:
1119 break;
1120 default:
1121 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1122 throw "stop execution";
1123 }
1124 break;
1125 case REC_TYPE_SECT:
1126 switch (fragType) {
1127 case INTERSECT_LINE:
1128 first = 1; last = 5; first2 = 8; last2 = 12;
1129 break;
1130 case INTERSECT_LINE_2:
1131 first = 1; last = 5; first2 = 11; last2 = 15;
1132 break;
1133 case INTERSECT_LINE_NO:
1134 first = 0; last = 4; first2 = 4; last2 = 8;
1135 break;
1136 case INTERSECT_QUAD_LINE:
1137 first = 1; last = 7; first2 = 10; last2 = 14;
1138 break;
1139 case INTERSECT_QUAD_LINE_2:
1140 first = 1; last = 7; first2 = 13; last2 = 17;
1141 break;
1142 case INTERSECT_QUAD_LINE_NO:
1143 first = 0; last = 6; first2 = 6; last2 = 10;
1144 break;
1145 case INTERSECT_QUAD:
1146 first = 1; last = 7; first2 = 10; last2 = 16;
1147 break;
1148 case INTERSECT_QUAD_2:
1149 first = 1; last = 7; first2 = 13; last2 = 19;
1150 break;
1151 case INTERSECT_QUAD_NO:
1152 first = 0; last = 6; first2 = 6; last2 = 12;
1153 break;
1154 case INTERSECT_SELF_CUBIC:
1155 first = 1; last = 9;
1156 break;
1157 case INTERSECT_SELF_CUBIC_NO:
1158 first = 0; last = 8;
1159 break;
1160 case INTERSECT_CUBIC_LINE:
1161 first = 1; last = 9; first2 = 12; last2 = 16;
1162 break;
1163 case INTERSECT_CUBIC_LINE_2:
1164 first = 1; last = 9; first2 = 15; last2 = 19;
1165 break;
1166 case INTERSECT_CUBIC_LINE_3:
1167 first = 1; last = 9; first2 = 18; last2 = 22;
1168 break;
1169 case INTERSECT_CUBIC_LINE_NO:
1170 first = 0; last = 8; first2 = 8; last2 = 12;
1171 break;
1172 case INTERSECT_CUBIC_QUAD:
1173 first = 1; last = 9; first2 = 12; last2 = 18;
1174 break;
1175 case INTERSECT_CUBIC_QUAD_2:
1176 first = 1; last = 9; first2 = 15; last2 = 21;
1177 break;
1178 case INTERSECT_CUBIC_QUAD_3:
1179 first = 1; last = 9; first2 = 18; last2 = 24;
1180 break;
1181 case INTERSECT_CUBIC_QUAD_4:
1182 first = 1; last = 9; first2 = 21; last2 = 27;
1183 break;
1184 case INTERSECT_CUBIC_QUAD_NO:
1185 first = 0; last = 8; first2 = 8; last2 = 14;
1186 break;
1187 case INTERSECT_CUBIC:
1188 first = 1; last = 9; first2 = 12; last2 = 20;
1189 break;
1190 case INTERSECT_CUBIC_2:
1191 first = 1; last = 9; first2 = 15; last2 = 23;
1192 break;
1193 case INTERSECT_CUBIC_3:
1194 first = 1; last = 9; first2 = 18; last2 = 26;
1195 break;
1196 case INTERSECT_CUBIC_4:
1197 first = 1; last = 9; first2 = 21; last2 = 29;
1198 break;
1199 case INTERSECT_CUBIC_NO:
1200 first = 0; last = 8; first2 = 8; last2 = 16;
1201 break;
1202 default:
1203 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1204 throw "stop execution";
1205 }
1206 break;
1207 default:
1208 continue;
1209 }
1210 for (var idx = first; idx < last; idx += 2) {
1211 xmin = Math.min(xmin, frags[idx]);
1212 xmax = Math.max(xmax, frags[idx]);
1213 ymin = Math.min(ymin, frags[idx + 1]);
1214 ymax = Math.max(ymax, frags[idx + 1]);
1215 }
1216 for (var idx = first2; idx < last2; idx += 2) {
1217 xmin = Math.min(xmin, frags[idx]);
1218 xmax = Math.max(xmax, frags[idx]);
1219 ymin = Math.min(ymin, frags[idx + 1]);
1220 ymax = Math.max(ymax, frags[idx + 1]);
1221 }
1222 }
1223 }
1224 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1225 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1226 var recType = test[tIndex];
1227 var records = test[tIndex + 2];
1228 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1229 var fragType = records[recordIndex];
1230 var frags = records[recordIndex + 1];
1231 switch (recType) {
1232 case REC_TYPE_ACTIVE_OP:
1233 if (!draw_op) {
1234 break;
1235 }
1236 {
1237 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1238 curve_extremes(curve, angleBounds);
1239 }
1240 break;
1241 case REC_TYPE_ANGLE:
1242 if (!draw_angle) {
1243 break;
1244 }
1245 if (fragType == ANGLE_AFTER) {
1246 var curve = curvePartialByID(test, frags[0], frags[3], frags[4]);
1247 curve_extremes(curve, angleBounds);
1248 curve = curvePartialByID(test, frags[5], frags[8], frags[9]);
1249 curve_extremes(curve, angleBounds);
1250 curve = curvePartialByID(test, frags[10], frags[13], frags[14]);
1251 } else if (fragType == ANGLE_AFTER2) {
1252 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1253 curve_extremes(curve, angleBounds);
1254 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1255 curve_extremes(curve, angleBounds);
1256 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1257 }
1258 break;
1259 case REC_TYPE_SORT:
1260 if (!draw_sort) {
1261 break;
1262 }
1263 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1264 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1265 curve_extremes(curve, angleBounds);
1266 }
1267 break;
1268 }
1269 }
1270 }
1271 xmin = Math.min(xmin, angleBounds[0]);
1272 ymin = Math.min(ymin, angleBounds[1]);
1273 xmax = Math.max(xmax, angleBounds[2]);
1274 ymax = Math.max(ymax, angleBounds[3]);
1275 setScale(xmin, xmax, ymin, ymax);
1276 if (hasPath == false && hasComputedPath == true && !draw_computed) {
1277 draw_computed = 3; // show both quadratics and cubics
1278 }
1279 if (hasPath == true && hasComputedPath == false && draw_computed) {
1280 draw_computed = 0;
1281 }
1282}
1283
1284function curveByID(test, id) {
1285 var tIndex = firstActiveSpan;
1286 if (tIndex < 0) {
1287 return [];
1288 }
1289 while (tIndex < test.length) {
1290 var recType = test[tIndex];
1291 if (recType != REC_TYPE_ACTIVE) {
1292 return [];
1293 }
1294 var records = test[tIndex + 2];
1295 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1296 var fragType = records[recordIndex];
1297 var frags = records[recordIndex + 1];
1298 if (frags[0] == id) {
1299 switch (fragType) {
1300 case ACTIVE_LINE_SPAN:
1301 return [frags[1], frags[2], frags[3], frags[4]];
1302 case ACTIVE_QUAD_SPAN:
1303 return [frags[1], frags[2], frags[3], frags[4],
1304 frags[5], frags[6]];
1305 case ACTIVE_CUBIC_SPAN:
1306 return [frags[1], frags[2], frags[3], frags[4],
1307 frags[5], frags[6], frags[7], frags[8]];
1308 }
1309 }
1310 }
1311 tIndex += 3;
1312 }
1313 return [];
1314}
1315
1316function curvePartialByID(test, id, t0, t1) {
1317 var tIndex = firstActiveSpan;
1318 if (tIndex < 0) {
1319 return [];
1320 }
1321 while (tIndex < test.length) {
1322 var recType = test[tIndex];
1323 if (recType != REC_TYPE_ACTIVE) {
1324 return [];
1325 }
1326 var records = test[tIndex + 2];
1327 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1328 var fragType = records[recordIndex];
1329 var frags = records[recordIndex + 1];
1330 if (frags[0] == id) {
1331 switch (fragType) {
1332 case ACTIVE_LINE_SPAN:
1333 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
1334 case ACTIVE_QUAD_SPAN:
1335 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1336 frags[5], frags[6], t0, t1);
1337 case ACTIVE_CUBIC_SPAN:
1338 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1339 frags[5], frags[6], frags[7], frags[8], t0, t1);
1340 }
1341 }
1342 }
1343 tIndex += 3;
1344 }
1345 return [];
1346}
1347
1348function idByCurve(test, frag, type) {
1349 var tIndex = firstActiveSpan;
1350 if (tIndex < 0) {
1351 return -1;
1352 }
1353 while (tIndex < test.length) {
1354 var recType = test[tIndex];
1355 if (recType != REC_TYPE_ACTIVE) {
1356 return -1;
1357 }
1358 var records = test[tIndex + 2];
1359 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1360 var fragType = records[recordIndex];
1361 var frags = records[recordIndex + 1];
1362 switch (fragType) {
1363 case ACTIVE_LINE_SPAN:
1364 if (type != PATH_LINE) {
1365 continue;
1366 }
1367 if (frag[0] != frags[1] || frag[1] != frags[2]
1368 || frag[2] != frags[3] || frag[3] != frags[4]) {
1369 continue;
1370 }
1371 return frags[0];
1372 case ACTIVE_QUAD_SPAN:
1373 if (type != PATH_QUAD) {
1374 continue;
1375 }
1376 if (frag[0] != frags[1] || frag[1] != frags[2]
1377 || frag[2] != frags[3] || frag[3] != frags[4]
1378 || frag[4] != frags[5] || frag[5] != frags[6]) {
1379 continue;
1380 }
1381 return frags[0];
1382 case ACTIVE_CUBIC_SPAN:
1383 if (type != PATH_CUBIC) {
1384 continue;
1385 }
1386 if (frag[0] != frags[1] || frag[1] != frags[2]
1387 || frag[2] != frags[3] || frag[3] != frags[4]
1388 || frag[4] != frags[5] || frag[5] != frags[6]
1389 || frag[6] != frags[7] || frag[7] != frags[8]) {
1390 continue;
1391 }
1392 return frags[0];
1393 }
1394 }
1395 ++tIndex;
1396 }
1397 return -1;
1398}
1399
1400function curve_extremes(curve, bounds) {
1401 for (var index = 0; index < curve.length; index += 2) {
1402 var x = curve[index];
1403 var y = curve[index + 1];
1404 bounds[0] = Math.min(bounds[0], x);
1405 bounds[1] = Math.min(bounds[1], y);
1406 bounds[2] = Math.max(bounds[2], x);
1407 bounds[3] = Math.max(bounds[3], y);
1408 }
1409}
1410
1411function setScale(x0, x1, y0, y1) {
1412 var srcWidth = x1 - x0;
1413 var srcHeight = y1 - y0;
1414 var usableWidth = screenWidth;
1415 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1416 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1417 usableWidth -= (xDigits + yDigits) * 10;
1418 usableWidth -= decimal_places * 10;
1419 if (draw_legend) {
1420 usableWidth -= 40;
1421 }
1422 var hscale = usableWidth / srcWidth;
1423 var vscale = screenHeight / srcHeight;
1424 scale = Math.min(hscale, vscale);
1425 var invScale = 1 / scale;
1426 var sxmin = x0 - invScale * 5;
1427 var symin = y0 - invScale * 10;
1428 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1429 var symax = y1 + invScale * 10;
1430 srcWidth = sxmax - sxmin;
1431 srcHeight = symax - symin;
1432 hscale = usableWidth / srcWidth;
1433 vscale = screenHeight / srcHeight;
1434 scale = Math.min(hscale, vscale);
1435 srcLeft = sxmin;
1436 srcTop = symin;
1437}
1438
1439function drawArc(curve, op, from, to) {
1440 var type = PATH_LINE + (curve.length / 2 - 2);
1441 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1442 var dy = pt.y - curve[1];
1443 var dx = pt.x - curve[0];
1444 var dist = Math.sqrt(dy * dy + dx * dx);
1445 var _dist = dist * scale;
1446 var angle = Math.atan2(dy, dx);
1447 var _px = (curve[0] - srcLeft) * scale;
1448 var _py = (curve[1] - srcTop) * scale;
1449 var divisor = 4;
1450 var endDist;
1451 do {
1452 var ends = [];
1453 for (var index = -1; index <= 1; index += 2) {
1454 var px = Math.cos(index * Math.PI / divisor);
1455 var py = Math.sin(index * Math.PI / divisor);
1456 ends.push(px);
1457 ends.push(py);
1458 }
1459 var endDx = (ends[2] - ends[0]) * scale * dist;
1460 var endDy = (ends[3] - ends[1]) * scale * dist;
1461 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1462 if (endDist < 100) {
1463 break;
1464 }
1465 divisor *= 2;
1466 } while (true);
1467 if (endDist < 30) {
1468 return;
1469 }
1470 if (op) {
1471 divisor *= 2;
1472 }
1473 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1474 ctx.beginPath();
1475 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1476 ctx.stroke();
1477 var saveAlign = ctx.textAlign;
1478 var saveStyle = ctx.fillStyle;
1479 var saveFont = ctx.font;
1480 ctx.textAlign = "center";
1481 ctx.fillStyle = "black";
1482 ctx.font = "normal 24px Arial";
1483 divisor *= 0.8;
1484 for (var index = -1; index <= 1; index += 2) {
1485 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1486 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1487 var _px = (px - srcLeft) * scale;
1488 var _py = (py - srcTop) * scale;
1489 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1490 }
1491 ctx.textAlign = saveAlign;
1492 ctx.fillStyle = saveStyle;
1493 ctx.font = saveFont;
1494}
1495
1496function drawPoint(px, py, end) {
1497 for (var pts = 0; pts < drawnPts.length; pts += 2) {
1498 var x = drawnPts[pts];
1499 var y = drawnPts[pts + 1];
1500 if (px == x && py == y) {
1501 return;
1502 }
1503 }
1504 drawnPts.push(px);
1505 drawnPts.push(py);
1506 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1507 var _px = (px - srcLeft) * scale;
1508 var _py = (py - srcTop) * scale;
1509 ctx.beginPath();
1510 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1511 ctx.closePath();
1512 if (end) {
1513 ctx.fill();
1514 } else {
1515 ctx.stroke();
1516 }
1517 if (debug_xy) {
1518 ctx.textAlign = "left";
1519 ctx.fillText(label, _px + 5, _py);
1520 }
1521}
1522
1523function drawPoints(ptArray, curveType, drawControls) {
1524 var count = (curveType - PATH_LINE + 2) * 2;
1525 for (var idx = 0; idx < count; idx += 2) {
1526 if (!drawControls && idx != 0 && idx != count - 2) {
1527 continue;
1528 }
1529 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1530 }
1531}
1532
1533function drawControlLines(curve, curveType, drawEnd) {
1534 if (curveType == PATH_LINE) {
1535 return;
1536 }
1537 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1538 drawLine(curve[0], curve[1], curve[2], curve[3]);
1539 drawLine(curve[2], curve[3], curve[4], curve[5]);
1540 if (curveType == PATH_CUBIC) {
1541 drawLine(curve[4], curve[5], curve[6], curve[7]);
1542 if (drawEnd > 1) {
1543 drawLine(curve[6], curve[7], curve[0], curve[1]);
1544 if (drawEnd > 2) {
1545 drawLine(curve[0], curve[1], curve[4], curve[5]);
1546 drawLine(curve[6], curve[7], curve[2], curve[3]);
1547 }
1548 }
1549 } else if (drawEnd > 1) {
1550 drawLine(curve[4], curve[5], curve[0], curve[1]);
1551 }
1552}
1553
1554function pointAtT(curve, curveType, t) {
1555 var xy = {};
1556 switch (curveType) {
1557 case PATH_LINE:
1558 var a = 1 - t;
1559 var b = t;
1560 xy.x = a * curve[0] + b * curve[2];
1561 xy.y = a * curve[1] + b * curve[3];
1562 break;
1563 case PATH_QUAD:
1564 var one_t = 1 - t;
1565 var a = one_t * one_t;
1566 var b = 2 * one_t * t;
1567 var c = t * t;
1568 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1569 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1570 break;
1571 case PATH_CUBIC:
1572 var one_t = 1 - t;
1573 var one_t2 = one_t * one_t;
1574 var a = one_t2 * one_t;
1575 var b = 3 * one_t2 * t;
1576 var t2 = t * t;
1577 var c = 3 * one_t * t2;
1578 var d = t2 * t;
1579 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1580 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1581 break;
1582 }
1583 return xy;
1584}
1585
1586function drawPointAtT(curve, curveType) {
1587 var x, y;
1588 var xy = pointAtT(curve, curveType, curveT);
1589 drawPoint(xy.x, xy.y, true);
1590 if (!draw_intersectT) {
1591 return;
1592 }
1593 ctx.fillStyle = "red";
1594 drawTAtPointUp(xy.x, xy.y, curveT);
1595}
1596
1597function drawTAtPointUp(px, py, t) {
1598 var label = t.toFixed(decimal_places);
1599 var _px = (px - srcLeft)* scale;
1600 var _py = (py - srcTop) * scale;
1601 ctx.fillText(label, _px + 5, _py - 10);
1602}
1603
1604function drawTAtPointDown(px, py, t) {
1605 var label = t.toFixed(decimal_places);
1606 var _px = (px - srcLeft)* scale;
1607 var _py = (py - srcTop) * scale;
1608 ctx.fillText(label, _px + 5, _py + 10);
1609}
1610
1611function alreadyDrawnLine(x1, y1, x2, y2) {
1612 if (collect_bounds) {
1613 if (focus_enabled) {
1614 focusXmin = Math.min(focusXmin, x1, x2);
1615 focusYmin = Math.min(focusYmin, y1, y2);
1616 focusXmax = Math.max(focusXmax, x1, x2);
1617 focusYmax = Math.max(focusYmax, y1, y2);
1618 }
1619 return true;
1620 }
1621 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1622 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1623 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1624 return true;
1625 }
1626 }
1627 drawnLines.push(x1);
1628 drawnLines.push(y1);
1629 drawnLines.push(x2);
1630 drawnLines.push(y2);
1631 return false;
1632}
1633
1634function drawLine(x1, y1, x2, y2) {
1635 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1636 return;
1637 }
1638 ctx.beginPath();
1639 ctx.moveTo((x1 - srcLeft) * scale,
1640 (y1 - srcTop) * scale);
1641 ctx.lineTo((x2 - srcLeft) * scale,
1642 (y2 - srcTop) * scale);
1643 ctx.stroke();
1644}
1645
1646function linePartial(x1, y1, x2, y2, t1, t2) {
1647 var dx = x1 - x2;
1648 var dy = y1 - y2;
1649 var array = [
1650 x1 - t1 * dx,
1651 y1 - t1 * dy,
1652 x1 - t2 * dx,
1653 y1 - t2 * dy
1654 ];
1655 return array;
1656}
1657
1658function drawLinePartial(x1, y1, x2, y2, t1, t2) {
1659 var a = linePartial(x1, y1, x2, y2, t1, t2);
1660 var ax = a[0];
1661 var ay = a[1];
1662 var bx = a[2];
1663 var by = a[3];
1664 if (alreadyDrawnLine(ax, ay, bx, by)) {
1665 return;
1666 }
1667 ctx.beginPath();
1668 ctx.moveTo((ax - srcLeft) * scale,
1669 (ay - srcTop) * scale);
1670 ctx.lineTo((bx - srcLeft) * scale,
1671 (by - srcTop) * scale);
1672 ctx.stroke();
1673}
1674
1675function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
1676 if (collect_bounds) {
1677 if (focus_enabled) {
1678 focusXmin = Math.min(focusXmin, x1, x2, x3);
1679 focusYmin = Math.min(focusYmin, y1, y2, y3);
1680 focusXmax = Math.max(focusXmax, x1, x2, x3);
1681 focusYmax = Math.max(focusYmax, y1, y2, y3);
1682 }
1683 return true;
1684 }
1685 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
1686 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
1687 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
1688 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
1689 return true;
1690 }
1691 }
1692 drawnQuads.push(x1);
1693 drawnQuads.push(y1);
1694 drawnQuads.push(x2);
1695 drawnQuads.push(y2);
1696 drawnQuads.push(x3);
1697 drawnQuads.push(y3);
1698 return false;
1699}
1700
1701function drawQuad(x1, y1, x2, y2, x3, y3) {
1702 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
1703 return;
1704 }
1705 ctx.beginPath();
1706 ctx.moveTo((x1 - srcLeft) * scale,
1707 (y1 - srcTop) * scale);
1708 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
1709 (y2 - srcTop) * scale,
1710 (x3 - srcLeft) * scale,
1711 (y3 - srcTop) * scale);
1712 ctx.stroke();
1713}
1714
1715function interp(A, B, t) {
1716 return A + (B - A) * t;
1717}
1718
1719function interp_quad_coords(x1, x2, x3, t)
1720{
1721 var ab = interp(x1, x2, t);
1722 var bc = interp(x2, x3, t);
1723 var abc = interp(ab, bc, t);
1724 return abc;
1725}
1726
1727function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1728 var ax = interp_quad_coords(x1, x2, x3, t1);
1729 var ay = interp_quad_coords(y1, y2, y3, t1);
1730 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
1731 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
1732 var cx = interp_quad_coords(x1, x2, x3, t2);
1733 var cy = interp_quad_coords(y1, y2, y3, t2);
1734 var bx = 2*dx - (ax + cx)/2;
1735 var by = 2*dy - (ay + cy)/2;
1736 var array = [
1737 ax, ay, bx, by, cx, cy
1738 ];
1739 return array;
1740}
1741
1742function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
1743 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
1744 var ax = a[0];
1745 var ay = a[1];
1746 var bx = a[2];
1747 var by = a[3];
1748 var cx = a[4];
1749 var cy = a[5];
1750 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
1751 return;
1752 }
1753 ctx.beginPath();
1754 ctx.moveTo((ax - srcLeft) * scale,
1755 (ay - srcTop) * scale);
1756 ctx.quadraticCurveTo((bx - srcLeft) * scale,
1757 (by - srcTop) * scale,
1758 (cx - srcLeft) * scale,
1759 (cy - srcTop) * scale);
1760 ctx.stroke();
1761}
1762
1763function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
1764 if (collect_bounds) {
1765 if (focus_enabled) {
1766 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
1767 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
1768 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
1769 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
1770 }
1771 return true;
1772 }
1773 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
1774 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
1775 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
1776 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
1777 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
1778 return true;
1779 }
1780 }
1781 drawnCubics.push(x1);
1782 drawnCubics.push(y1);
1783 drawnCubics.push(x2);
1784 drawnCubics.push(y2);
1785 drawnCubics.push(x3);
1786 drawnCubics.push(y3);
1787 drawnCubics.push(x4);
1788 drawnCubics.push(y4);
1789 return false;
1790}
1791
1792function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
1793 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
1794 return;
1795 }
1796 ctx.beginPath();
1797 ctx.moveTo((x1 - srcLeft) * scale,
1798 (y1 - srcTop) * scale);
1799 ctx.bezierCurveTo((x2 - srcLeft) * scale,
1800 (y2 - srcTop) * scale,
1801 (x3 - srcLeft) * scale,
1802 (y3 - srcTop) * scale,
1803 (x4 - srcLeft) * scale,
1804 (y4 - srcTop) * scale);
1805 ctx.stroke();
1806}
1807
1808function interp_cubic_coords(x1, x2, x3, x4, t)
1809{
1810 var ab = interp(x1, x2, t);
1811 var bc = interp(x2, x3, t);
1812 var cd = interp(x3, x4, t);
1813 var abc = interp(ab, bc, t);
1814 var bcd = interp(bc, cd, t);
1815 var abcd = interp(abc, bcd, t);
1816 return abcd;
1817}
1818
1819function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
1820 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
1821 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
1822 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
1823 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
1824 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
1825 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
1826 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
1827 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
1828 var mx = ex * 27 - ax * 8 - dx;
1829 var my = ey * 27 - ay * 8 - dy;
1830 var nx = fx * 27 - ax - dx * 8;
1831 var ny = fy * 27 - ay - dy * 8;
1832 var bx = (mx * 2 - nx) / 18;
1833 var by = (my * 2 - ny) / 18;
1834 var cx = (nx * 2 - mx) / 18;
1835 var cy = (ny * 2 - my) / 18;
1836 var array = [
1837 ax, ay, bx, by, cx, cy, dx, dy
1838 ];
1839 return array;
1840}
1841
1842function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
1843 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
1844 var ax = a[0];
1845 var ay = a[1];
1846 var bx = a[2];
1847 var by = a[3];
1848 var cx = a[4];
1849 var cy = a[5];
1850 var dx = a[6];
1851 var dy = a[7];
1852 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
1853 return;
1854 }
1855 ctx.beginPath();
1856 ctx.moveTo((ax - srcLeft) * scale,
1857 (ay - srcTop) * scale);
1858 ctx.bezierCurveTo((bx - srcLeft) * scale,
1859 (by - srcTop) * scale,
1860 (cx - srcLeft) * scale,
1861 (cy - srcTop) * scale,
1862 (dx - srcLeft) * scale,
1863 (dy - srcTop) * scale);
1864 ctx.stroke();
1865}
1866
1867function drawCurve(c) {
1868 switch (c.length) {
1869 case 4:
1870 drawLine(c[0], c[1], c[2], c[3]);
1871 break;
1872 case 6:
1873 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
1874 break;
1875 case 8:
1876 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
1877 break;
1878 }
1879}
1880
1881function boundsWidth(pts) {
1882 var min = pts[0];
1883 var max = pts[0];
1884 for (var idx = 2; idx < pts.length; idx += 2) {
1885 min = Math.min(min, pts[idx]);
1886 max = Math.max(max, pts[idx]);
1887 }
1888 return max - min;
1889}
1890
1891function boundsHeight(pts) {
1892 var min = pts[1];
1893 var max = pts[1];
1894 for (var idx = 3; idx < pts.length; idx += 2) {
1895 min = Math.min(min, pts[idx]);
1896 max = Math.max(max, pts[idx]);
1897 }
1898 return max - min;
1899}
1900
1901function tangent(pts) {
1902 var dx = pts[2] - pts[0];
1903 var dy = pts[3] - pts[1];
1904 if (dx == 0 && dy == 0 && pts.length > 4) {
1905 dx = pts[4] - pts[0];
1906 dy = pts[5] - pts[1];
1907 if (dx == 0 && dy == 0 && pts.length > 6) {
1908 dx = pts[6] - pts[0];
1909 dy = pts[7] - pts[1];
1910 }
1911 }
1912 return Math.atan2(-dy, dx);
1913}
1914
1915function hodograph(cubic) {
1916 var hodo = [];
1917 hodo[0] = 3 * (cubic[2] - cubic[0]);
1918 hodo[1] = 3 * (cubic[3] - cubic[1]);
1919 hodo[2] = 3 * (cubic[4] - cubic[2]);
1920 hodo[3] = 3 * (cubic[5] - cubic[3]);
1921 hodo[4] = 3 * (cubic[6] - cubic[4]);
1922 hodo[5] = 3 * (cubic[7] - cubic[5]);
1923 return hodo;
1924}
1925
1926function hodograph2(cubic) {
1927 var quad = hodograph(cubic);
1928 var hodo = [];
1929 hodo[0] = 2 * (quad[2] - quad[0]);
1930 hodo[1] = 2 * (quad[3] - quad[1]);
1931 hodo[2] = 2 * (quad[4] - quad[2]);
1932 hodo[3] = 2 * (quad[5] - quad[3]);
1933 return hodo;
1934}
1935
1936function quadraticRootsReal(A, B, C, s) {
1937 if (A == 0) {
1938 if (B == 0) {
1939 s[0] = 0;
1940 return C == 0;
1941 }
1942 s[0] = -C / B;
1943 return 1;
1944 }
1945 /* normal form: x^2 + px + q = 0 */
1946 var p = B / (2 * A);
1947 var q = C / A;
1948 var p2 = p * p;
1949 if (p2 < q) {
1950 return 0;
1951 }
1952 var sqrt_D = 0;
1953 if (p2 > q) {
1954 sqrt_D = sqrt(p2 - q);
1955 }
1956 s[0] = sqrt_D - p;
1957 s[1] = -sqrt_D - p;
1958 return 1 + s[0] != s[1];
1959}
1960
1961function add_valid_ts(s, realRoots, t) {
1962 var foundRoots = 0;
1963 for (var index = 0; index < realRoots; ++index) {
1964 var tValue = s[index];
1965 if (tValue >= 0 && tValue <= 1) {
1966 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
1967 if (t[idx2] != tValue) {
1968 t[foundRoots++] = tValue;
1969 }
1970 }
1971 }
1972 }
1973 return foundRoots;
1974}
1975
1976function quadraticRootsValidT(a, b, c, t) {
1977 var s = [];
1978 var realRoots = quadraticRootsReal(A, B, C, s);
1979 var foundRoots = add_valid_ts(s, realRoots, t);
1980 return foundRoots != 0;
1981}
1982
1983function find_cubic_inflections(cubic, tValues) {
1984 var Ax = src[2] - src[0];
1985 var Ay = src[3] - src[1];
1986 var Bx = src[4] - 2 * src[2] + src[0];
1987 var By = src[5] - 2 * src[3] + src[1];
1988 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
1989 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
1990 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
1991 Ax * By - Ay * Bx, tValues);
1992}
1993
1994function dxy_at_t(curve, type, t) {
1995 var dxy = {};
1996 if (type == PATH_QUAD) {
1997 var a = t - 1;
1998 var b = 1 - 2 * t;
1999 var c = t;
2000 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2001 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
2002 } else if (type == PATH_CUBIC) {
2003 var one_t = 1 - t;
2004 var a = curve[0];
2005 var b = curve[2];
2006 var c = curve[4];
2007 var d = curve[6];
2008 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2009 a = curve[1];
2010 b = curve[3];
2011 c = curve[5];
2012 d = curve[7];
2013 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2014 }
2015 return dxy;
2016}
2017
2018function drawLabel(num, px, py) {
2019 ctx.beginPath();
2020 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2021 ctx.closePath();
2022 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2023 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2024 ctx.stroke();
2025 ctx.fillStyle = "black";
2026 ctx.font = "normal 10px Arial";
2027 // ctx.rotate(0.001);
2028 ctx.fillText(num, px - 2, py + 3);
2029 // ctx.rotate(-0.001);
2030}
2031
2032function drawLabelX(ymin, num, loc) {
2033 var px = (loc - srcLeft) * scale;
2034 var py = (ymin - srcTop) * scale - 20;
2035 drawLabel(num, px, py);
2036}
2037
2038function drawLabelY(xmin, num, loc) {
2039 var px = (xmin - srcLeft) * scale - 20;
2040 var py = (loc - srcTop) * scale;
2041 drawLabel(num, px, py);
2042}
2043
2044function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2045 ctx.beginPath();
2046 ctx.moveTo(hx, hy - 100);
2047 ctx.lineTo(hx, hy);
2048 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2049 ctx.stroke();
2050 ctx.beginPath();
2051 ctx.moveTo(hx, hy);
2052 ctx.lineTo(hx, hy + 100);
2053 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2054 ctx.stroke();
2055 ctx.beginPath();
2056 ctx.moveTo(hx - 100, hy);
2057 ctx.lineTo(hx, hy);
2058 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2059 ctx.stroke();
2060 ctx.beginPath();
2061 ctx.moveTo(hx, hy);
2062 ctx.lineTo(hx + 100, hy);
2063 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2064 ctx.stroke();
2065}
2066
2067function scalexy(x, y, mag) {
2068 var length = Math.sqrt(x * x + y * y);
2069 return mag / length;
2070}
2071
2072function drawArrow(x, y, dx, dy) {
2073 var dscale = scalexy(dx, dy, 1 / scale * 100);
2074 dx *= dscale;
2075 dy *= dscale;
2076 ctx.beginPath();
2077 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2078 x += dx;
2079 y += dy;
2080 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2081 dx /= 10;
2082 dy /= 10;
2083 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2084 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2085 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2086 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2087 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2088 ctx.stroke();
2089}
2090
2091function x_at_t(curve, t) {
2092 var one_t = 1 - t;
2093 if (curve.length == 4) {
2094 return one_t * curve[0] + t * curve[2];
2095 }
2096 var one_t2 = one_t * one_t;
2097 var t2 = t * t;
2098 if (curve.length == 6) {
2099 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2100 }
2101 var a = one_t2 * one_t;
2102 var b = 3 * one_t2 * t;
2103 var c = 3 * one_t * t2;
2104 var d = t2 * t;
2105 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2106}
2107
2108function y_at_t(curve, t) {
2109 var one_t = 1 - t;
2110 if (curve.length == 4) {
2111 return one_t * curve[1] + t * curve[3];
2112 }
2113 var one_t2 = one_t * one_t;
2114 var t2 = t * t;
2115 if (curve.length == 6) {
2116 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2117 }
2118 var a = one_t2 * one_t;
2119 var b = 3 * one_t2 * t;
2120 var c = 3 * one_t * t2;
2121 var d = t2 * t;
2122 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2123}
2124
2125function drawOrder(curve, label) {
2126 var px = x_at_t(curve, 0.75);
2127 var py = y_at_t(curve, 0.75);
2128 var _px = (px - srcLeft) * scale;
2129 var _py = (py - srcTop) * scale;
2130 ctx.beginPath();
2131 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2132 ctx.closePath();
2133 ctx.fillStyle = "white";
2134 ctx.fill();
2135 if (label == 'L') {
2136 ctx.strokeStyle = "rgba(255,0,0, 1)";
2137 ctx.fillStyle = "rgba(255,0,0, 1)";
2138 } else {
2139 ctx.strokeStyle = "rgba(0,0,255, 1)";
2140 ctx.fillStyle = "rgba(0,0,255, 1)";
2141 }
2142 ctx.stroke();
2143 ctx.font = "normal 16px Arial";
2144 ctx.textAlign = "center";
2145 ctx.fillText(label, _px, _py + 5);
2146 ctx.font = "normal 10px Arial";
2147}
2148
2149function drawID(curve, id) {
2150 var px = x_at_t(curve, 0.5);
2151 var py = y_at_t(curve, 0.5);
2152 var _px = (px - srcLeft) * scale;
2153 var _py = (py - srcTop) * scale;
2154 draw_id_at(id, _px, _py);
2155}
2156
2157function draw_id_at(id, _px, _py) {
2158 ctx.beginPath();
2159 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2160 ctx.closePath();
2161 ctx.fillStyle = "white";
2162 ctx.fill();
2163 ctx.strokeStyle = "rgba(127,127,0, 1)";
2164 ctx.fillStyle = "rgba(127,127,0, 1)";
2165 ctx.stroke();
2166 ctx.font = "normal 16px Arial";
2167 ctx.textAlign = "center";
2168 ctx.fillText(id, _px, _py + 5);
2169 ctx.font = "normal 10px Arial";
2170}
2171
2172function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2173 var curve = [x1, y1, x2, y2];
2174 drawCurvePartialID(id, curve, t1, t2);
2175}
2176
2177function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2178 var curve = [x1, y1, x2, y2, x3, y3];
2179 drawCurvePartialID(id, curve, t1, t2);
2180}
2181
2182function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2183 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2184 drawCurvePartialID(id, curve, t1, t2);
2185}
2186
2187function drawCurvePartialID(id, curve, t1, t2) {
2188 var px = x_at_t(curve, (t1 + t2) / 2);
2189 var py = y_at_t(curve, (t1 + t2) / 2);
2190 var _px = (px - srcLeft) * scale;
2191 var _py = (py - srcTop) * scale;
2192 draw_id_at(id, _px, _py);
2193}
2194
2195function drawCurveSpecials(test, curve, type) {
2196 if (pt_labels) {
2197 drawPoints(curve, type, pt_labels == 2);
2198 }
2199 if (control_lines != 0) {
2200 drawControlLines(curve, type, control_lines);
2201 }
2202 if (curve_t) {
2203 drawPointAtT(curve, type);
2204 }
2205 if (draw_midpoint) {
2206 var mid = pointAtT(curve, type, 0.5);
2207 drawPoint(mid.x, mid.y, true);
2208 }
2209 if (draw_id) {
2210 var id = idByCurve(test, curve, type);
2211 if (id >= 0) {
2212 drawID(curve, id);
2213 }
2214 }
2215 if (type == PATH_LINE) {
2216 return;
2217 }
2218 if (draw_deriviatives > 0) {
2219 var d = dxy_at_t(curve, type, 0);
2220 drawArrow(curve[0], curve[1], d.x, d.y);
2221 if (draw_deriviatives == 2) {
2222 d = dxy_at_t(curve, type, 1);
2223 if (type == PATH_CUBIC) {
2224 drawArrow(curve[6], curve[7], d.x, d.y);
2225 } else {
2226 drawArrow(curve[4], curve[5], d.x, d.y);
2227 }
2228 }
2229 if (draw_midpoint) {
2230 var mid = pointAtT(curve, type, 0.5);
2231 d = dxy_at_t(curve, type, 0.5);
2232 drawArrow(mid.x, mid.y, d.x, d.y);
2233 }
2234 }
2235 if (type != PATH_CUBIC) {
2236 return;
2237 }
2238 if (draw_hodo == 1 || draw_hodo == 2) {
2239 var hodo = hodograph(curve);
2240 var hMinX = Math.min(0, hodo[0], hodo[2], hodo[4]);
2241 var hMinY = Math.min(0, hodo[1], hodo[3], hodo[5]);
2242 var hMaxX = Math.max(0, hodo[0], hodo[2], hodo[4]);
2243 var hMaxY = Math.max(0, hodo[1], hodo[3], hodo[5]);
2244 var hScaleX = hMaxX - hMinX > 0 ? screenWidth / (hMaxX - hMinX) : 1;
2245 var hScaleY = hMaxY - hMinY > 0 ? screenHeight / (hMaxY - hMinY) : 1;
2246 var hUnit = Math.min(hScaleX, hScaleY);
2247 hUnit /= 2;
2248 var hx = xoffset - hMinX * hUnit;
2249 var hy = yoffset - hMinY * hUnit;
2250 ctx.moveTo(hx + hodo[0] * hUnit, hy + hodo[1] * hUnit);
2251 ctx.quadraticCurveTo(
2252 hx + hodo[2] * hUnit, hy + hodo[3] * hUnit,
2253 hx + hodo[4] * hUnit, hy + hodo[5] * hUnit);
2254 ctx.strokeStyle = "red";
2255 ctx.stroke();
2256 if (draw_hodo == 1) {
2257 drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY);
2258 }
2259 }
2260 if (draw_hodo == 3) {
2261 var hodo = hodograph2(curve);
2262 var hMinX = Math.min(0, hodo[0], hodo[2]);
2263 var hMinY = Math.min(0, hodo[1], hodo[3]);
2264 var hMaxX = Math.max(0, hodo[0], hodo[2]);
2265 var hMaxY = Math.max(0, hodo[1], hodo[3]);
2266 var hScaleX = hMaxX - hMinX > 0 ? screenWidth / (hMaxX - hMinX) : 1;
2267 var hScaleY = hMaxY - hMinY > 0 ? screenHeight / (hMaxY - hMinY) : 1;
2268 var hUnit = Math.min(hScaleX, hScaleY);
2269 hUnit /= 2;
2270 var hx = xoffset - hMinX * hUnit;
2271 var hy = yoffset - hMinY * hUnit;
2272 ctx.moveTo(hx + hodo[0] * hUnit, hy + hodo[1] * hUnit);
2273 ctx.lineTo(hx + hodo[2] * hUnit, hy + hodo[3] * hUnit);
2274 ctx.strokeStyle = "red";
2275 ctx.stroke();
2276 drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY);
2277 }
2278 if (draw_sequence) {
2279 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2280 for (var i = 0; i < 8; i+= 2) {
2281 drawLabelX(ymin, i >> 1, curve[i]);
2282 }
2283 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2284 for (var i = 1; i < 8; i+= 2) {
2285 drawLabelY(xmin, i >> 1, curve[i]);
2286 }
2287 }
2288}
2289
2290function logCurves(test) {
2291 for (curves in test) {
2292 var curve = test[curves];
2293 dumpCurve(curve);
2294 }
2295}
2296
2297function curveToString(curve) {
2298 var str = "{{";
2299 for (i = 0; i < curve.length; i += 2) {
2300 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2301 if (i < curve.length - 2) {
2302 str += "}, {";
2303 }
2304 }
2305 str += "}}";
2306 return str;
2307}
2308
2309function dumpCurve(curve) {
2310 console.log(curveToString(curve));
2311}
2312
2313function draw(test, lines, title) {
2314 ctx.fillStyle = "rgba(0,0,0, 0.1)";
2315 ctx.font = "normal 50px Arial";
2316 ctx.textAlign = "left";
2317 ctx.fillText(title, 50, 50);
2318 ctx.font = "normal 10px Arial";
2319 ctx.lineWidth = "1.001"; "0.999";
2320 var secondPath = test.length;
2321 var closeCount = 0;
2322 logStart = -1;
2323 logRange = 0;
2324 // find last active rec type at this step
2325 var curType = test[0];
2326 var curStep = 0;
2327 var hasOp = false;
2328 var lastActive = 0;
2329 var lastAdd = 0;
2330 var lastSect = 0;
2331 var lastSort = 0;
2332 var lastMark = 0;
2333 activeCount = 0;
2334 addCount = 0;
2335 angleCount = 0;
2336 opCount = 0;
2337 sectCount = 0;
2338 sortCount = 0;
2339 markCount = 0;
2340 activeMax = 0;
2341 addMax = 0;
2342 angleMax = 0;
2343 opMax = 0;
2344 sectMax = 0;
2345 sectMax2 = 0;
2346 sortMax = 0;
2347 markMax = 0;
2348 lastIndex = test.length - 3;
2349 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
2350 var recType = test[tIndex];
2351 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
2352 console.log("unknown rec type: " + recType);
2353 throw "stop execution";
2354 }
2355 // if (curType == recType && curType != REC_TYPE_ADD) {
2356 // continue;
2357 // }
2358 var inStepRange = step_limit == 0 || curStep < step_limit;
2359 curType = recType;
2360 if (recType == REC_TYPE_OP) {
2361 hasOp = true;
2362 continue;
2363 }
2364 if (recType == REC_TYPE_UNKNOWN) {
2365 // these types do not advance step
2366 continue;
2367 }
2368 var bumpStep = false;
2369 var records = test[tIndex + 2];
2370 var fragType = records[0];
2371 if (recType == REC_TYPE_ADD) {
2372 if (records.length != 2) {
2373 console.log("expect only two elements: " + records.length);
2374 throw "stop execution";
2375 }
2376 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
2377 continue;
2378 }
2379 ++addMax;
2380 if (!draw_add || !inStepRange) {
2381 continue;
2382 }
2383 lastAdd = tIndex;
2384 ++addCount;
2385 bumpStep = true;
2386 }
2387 if (recType == REC_TYPE_PATH && hasOp) {
2388 secondPath = tIndex;
2389 }
2390 if (recType == REC_TYPE_ACTIVE) {
2391 ++activeMax;
2392 if (!draw_active || !inStepRange) {
2393 continue;
2394 }
2395 lastActive = tIndex;
2396 ++activeCount;
2397 bumpStep = true;
2398 }
2399 if (recType == REC_TYPE_ACTIVE_OP) {
2400 ++opMax;
2401 if (!draw_op || !inStepRange) {
2402 continue;
2403 }
2404 lastOp = tIndex;
2405 ++opCount;
2406 bumpStep = true;
2407 }
2408 if (recType == REC_TYPE_ANGLE) {
2409 ++angleMax;
2410 if (!draw_angle || !inStepRange) {
2411 continue;
2412 }
2413 lastAngle = tIndex;
2414 ++angleCount;
2415 bumpStep = true;
2416 }
2417 if (recType == REC_TYPE_SECT) {
2418 if (records.length != 2) {
2419 console.log("expect only two elements: " + records.length);
2420 throw "stop execution";
2421 }
2422 ++sectMax;
2423 var sectBump = 1;
2424 switch (fragType) {
2425 case INTERSECT_LINE:
2426 case INTERSECT_QUAD_LINE:
2427 case INTERSECT_QUAD:
2428 case INTERSECT_SELF_CUBIC:
2429 case INTERSECT_CUBIC_LINE:
2430 case INTERSECT_CUBIC_QUAD:
2431 case INTERSECT_CUBIC:
2432 sectBump = 1;
2433 break;
2434 case INTERSECT_LINE_2:
2435 case INTERSECT_QUAD_LINE_2:
2436 case INTERSECT_QUAD_2:
2437 case INTERSECT_CUBIC_LINE_2:
2438 case INTERSECT_CUBIC_QUAD_2:
2439 case INTERSECT_CUBIC_2:
2440 sectBump = 2;
2441 break;
2442 case INTERSECT_LINE_NO:
2443 case INTERSECT_QUAD_LINE_NO:
2444 case INTERSECT_QUAD_NO:
2445 case INTERSECT_SELF_CUBIC_NO:
2446 case INTERSECT_CUBIC_LINE_NO:
2447 case INTERSECT_CUBIC_QUAD_NO:
2448 case INTERSECT_CUBIC_NO:
2449 sectBump = 0;
2450 break;
2451 case INTERSECT_CUBIC_LINE_3:
2452 case INTERSECT_CUBIC_QUAD_3:
2453 case INTERSECT_CUBIC_3:
2454 sectBump = 3;
2455 break;
2456 case INTERSECT_CUBIC_QUAD_4:
2457 case INTERSECT_CUBIC_4:
2458 sectBump = 4;
2459 break;
2460 default:
2461 console.log("missing case " + records.length);
2462 throw "stop execution";
2463 }
2464 sectMax2 += sectBump;
2465 if (draw_intersection <= 1 || !inStepRange) {
2466 continue;
2467 }
2468 lastSect = tIndex;
2469 sectCount += sectBump;
2470 bumpStep = true;
2471 }
2472 if (recType == REC_TYPE_SORT) {
2473 ++sortMax;
2474 if (!draw_sort || !inStepRange) {
2475 continue;
2476 }
2477 lastSort = tIndex;
2478 ++sortCount;
2479 bumpStep = true;
2480 }
2481 if (recType == REC_TYPE_MARK) {
2482 ++markMax;
2483 if (!draw_mark || !inStepRange) {
2484 continue;
2485 }
2486 lastMark = tIndex;
2487 ++markCount;
2488 bumpStep = true;
2489 }
2490 if (bumpStep) {
2491 lastIndex = tIndex;
2492 logStart = test[tIndex + 1];
2493 logRange = records.length / 2;
2494 ++curStep;
2495 }
2496 }
2497 stepMax = (draw_add ? addMax : 0)
2498 + (draw_active ? activeMax : 0)
2499 + (draw_op ? opMax : 0)
2500 + (draw_angle ? angleMax : 0)
2501 + (draw_sort ? sortMax : 0)
2502 + (draw_mark ? markMax : 0)
2503 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
2504 if (stepMax == 0) {
2505 stepMax = addMax + activeMax + angleMax + opMax + sortMax + markMax;
2506 }
2507 drawnPts = [];
2508 drawnLines = [];
2509 drawnQuads = [];
2510 drawnCubics = [];
2511 focusXmin = focusYmin = Infinity;
2512 focusXmax = focusYmax = -Infinity;
2513 var pathIndex = 0;
2514 var opLetter = 'S';
2515 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
2516 var recType = test[tIndex];
2517 var records = test[tIndex + 2];
2518 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
2519 var fragType = records[recordIndex];
2520 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
2521 console.log("unknown in range frag type: " + fragType);
2522 throw "stop execution";
2523 }
2524 var frags = records[recordIndex + 1];
2525 focus_enabled = false;
2526 switch (recType) {
2527 case REC_TYPE_COMPUTED:
2528 if (draw_computed == 0) {
2529 continue;
2530 }
2531 ctx.lineWidth = 1;
2532 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
2533 ctx.fillStyle = "blue";
2534 var drawThis = false;
2535 switch (fragType) {
2536 case PATH_QUAD:
2537 if ((draw_computed & 5) == 1 || ((draw_computed & 4) != 0
2538 && (draw_computed & 1) == pathIndex)) {
2539 drawQuad(frags[0], frags[1], frags[2], frags[3],
2540 frags[4], frags[5]);
2541 drawThis = true;
2542 }
2543 break;
2544 case PATH_CUBIC:
2545 if ((draw_computed & 6) == 2 || ((draw_computed & 4) != 0
2546 && (draw_computed & 1) != pathIndex)) {
2547 drawCubic(frags[0], frags[1], frags[2], frags[3],
2548 frags[4], frags[5], frags[6], frags[7]);
2549 drawThis = true;
2550 }
2551 ++pathIndex;
2552 break;
2553 case COMPUTED_SET_1:
2554 pathIndex = 0;
2555 break;
2556 case COMPUTED_SET_2:
2557 pathIndex = 1;
2558 break;
2559 default:
2560 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
2561 throw "stop execution";
2562 }
2563 if (!drawThis || collect_bounds) {
2564 break;
2565 }
2566 drawCurveSpecials(test, frags, fragType);
2567 break;
2568 case REC_TYPE_PATH:
2569 if (!draw_path) {
2570 continue;
2571 }
2572 var firstPath = tIndex < secondPath;
2573 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
2574 continue;
2575 }
2576 ctx.lineWidth = 1;
2577 ctx.strokeStyle = firstPath ? "black" : "red";
2578 ctx.fillStyle = "blue";
2579 switch (fragType) {
2580 case PATH_LINE:
2581 drawLine(frags[0], frags[1], frags[2], frags[3]);
2582 break;
2583 case PATH_QUAD:
2584 drawQuad(frags[0], frags[1], frags[2], frags[3],
2585 frags[4], frags[5]);
2586 break;
2587 case PATH_CUBIC:
2588 drawCubic(frags[0], frags[1], frags[2], frags[3],
2589 frags[4], frags[5], frags[6], frags[7]);
2590 break;
2591 default:
2592 console.log("unknown REC_TYPE_PATH frag type: " + fragType);
2593 throw "stop execution";
2594 }
2595 if (collect_bounds) {
2596 break;
2597 }
2598 drawCurveSpecials(test, frags, fragType);
2599 break;
2600 case REC_TYPE_OP:
2601 switch (fragType) {
2602 case OP_INTERSECT: opLetter = 'I'; break;
2603 case OP_DIFFERENCE: opLetter = 'D'; break;
2604 case OP_UNION: opLetter = 'U'; break;
2605 case OP_XOR: opLetter = 'X'; break;
2606 default:
2607 console.log("unknown REC_TYPE_OP frag type: " + fragType);
2608 throw "stop execution";
2609 }
2610 break;
2611 case REC_TYPE_ACTIVE:
2612 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
2613 continue;
2614 }
2615 var x1 = frags[SPAN_X1];
2616 var y1 = frags[SPAN_Y1];
2617 var x2 = frags[SPAN_X2];
2618 var y2 = frags[SPAN_Y2];
2619 var x3, y3, x3, y4, t1, t2;
2620 ctx.lineWidth = 3;
2621 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2622 focus_enabled = true;
2623 switch (fragType) {
2624 case ACTIVE_LINE_SPAN:
2625 t1 = frags[SPAN_L_T];
2626 t2 = frags[SPAN_L_TEND];
2627 drawLinePartial(x1, y1, x2, y2, t1, t2);
2628 if (draw_id) {
2629 drawLinePartialID(frags[0], x1, y1, x2, y2, t1, t2);
2630 }
2631 break;
2632 case ACTIVE_QUAD_SPAN:
2633 x3 = frags[SPAN_X3];
2634 y3 = frags[SPAN_Y3];
2635 t1 = frags[SPAN_Q_T];
2636 t2 = frags[SPAN_Q_TEND];
2637 drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2638 if (draw_id) {
2639 drawQuadPartialID(frags[0], x1, y1, x2, y2, x3, y3, t1, t2);
2640 }
2641 break;
2642 case ACTIVE_CUBIC_SPAN:
2643 x3 = frags[SPAN_X3];
2644 y3 = frags[SPAN_Y3];
2645 x4 = frags[SPAN_X4];
2646 y4 = frags[SPAN_Y4];
2647 t1 = frags[SPAN_C_T];
2648 t2 = frags[SPAN_C_TEND];
2649 drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2650 if (draw_id) {
2651 drawCubicPartialID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2652 }
2653 break;
2654 default:
2655 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
2656 throw "stop execution";
2657 }
2658 break;
2659 case REC_TYPE_ACTIVE_OP:
2660 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
2661 continue;
2662 }
2663 focus_enabled = true;
2664 ctx.lineWidth = 3;
2665 var activeSpan = frags[7] == "1";
2666 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
2667 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
2668 drawCurve(curve);
2669 if (draw_op > 1) {
2670 drawArc(curve, false, frags[3], frags[4]);
2671 drawArc(curve, true, frags[5], frags[6]);
2672 }
2673 break;
2674 case REC_TYPE_ADD:
2675 if (!draw_add) {
2676 continue;
2677 }
2678 ctx.lineWidth = 3;
2679 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
2680 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
2681 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
2682 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
2683 : "rgba(127,0,127, 0.3)";
2684 focus_enabled = true;
2685 switch (fragType) {
2686 case ADD_MOVETO:
2687 break;
2688 case ADD_LINETO:
2689 if (step_limit == 0 || tIndex >= lastAdd) {
2690 drawLine(frags[0], frags[1], frags[2], frags[3]);
2691 }
2692 break;
2693 case ADD_QUADTO:
2694 if (step_limit == 0 || tIndex >= lastAdd) {
2695 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
2696 }
2697 break;
2698 case ADD_CUBICTO:
2699 if (step_limit == 0 || tIndex >= lastAdd) {
2700 drawCubic(frags[0], frags[1], frags[2], frags[3],
2701 frags[4], frags[5], frags[6], frags[7]);
2702 }
2703 break;
2704 case ADD_CLOSE:
2705 ++closeCount;
2706 break;
2707 case ADD_FILL:
2708 break;
2709 default:
2710 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
2711 throw "stop execution";
2712 }
2713 break;
2714 case REC_TYPE_ANGLE:
2715 if (!draw_angle || (step_limit > 0 && tIndex < lastAngle)) {
2716 continue;
2717 }
2718 if (fragType != ANGLE_AFTER && fragType != ANGLE_AFTER2) {
2719 continue;
2720 }
2721 focus_enabled = true;
2722 ctx.lineWidth = 3;
2723 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
2724 var leftCurve, midCurve, rightCurve;
2725 if (fragType == ANGLE_AFTER) {
2726 leftCurve = curvePartialByID(test, frags[0], frags[3], frags[4]);
2727 midCurve = curvePartialByID(test, frags[5], frags[8], frags[9]);
2728 rightCurve = curvePartialByID(test, frags[10], frags[13], frags[14]);
2729 } else {
2730 leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
2731 midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
2732 rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
2733 }
2734 drawCurve(leftCurve);
2735 drawCurve(rightCurve);
2736 var inBetween = frags[fragType == ANGLE_AFTER ? 15 : 18] == "T";
2737 ctx.strokeStyle = inBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
2738 drawCurve(midCurve);
2739 if (draw_angle > 1) {
2740 drawOrder(leftCurve, 'L');
2741 drawOrder(rightCurve, 'R');
2742 }
2743 break;
2744 case REC_TYPE_SECT:
2745 if (!draw_intersection) {
2746 continue;
2747 }
2748 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
2749 continue;
2750 }
2751 // draw_intersection == 1 : show all
2752 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
2753 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
2754 ctx.lineWidth = 1;
2755 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
2756 ctx.fillStyle = "blue";
2757 focus_enabled = true;
2758 var f = [];
2759 var c1s;
2760 var c1l;
2761 var c2s;
2762 var c2l;
2763 switch (fragType) {
2764 case INTERSECT_LINE:
2765 f.push(5, 6, 0, 7);
2766 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
2767 break;
2768 case INTERSECT_LINE_2:
2769 f.push(5, 6, 0, 10);
2770 f.push(8, 9, 7, 15);
2771 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
2772 break;
2773 case INTERSECT_LINE_NO:
2774 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
2775 break;
2776 case INTERSECT_QUAD_LINE:
2777 f.push(7, 8, 0, 9);
2778 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
2779 break;
2780 case INTERSECT_QUAD_LINE_2:
2781 f.push(7, 8, 0, 12);
2782 f.push(10, 11, 9, 17);
2783 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
2784 break;
2785 case INTERSECT_QUAD_LINE_NO:
2786 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
2787 break;
2788 case INTERSECT_QUAD:
2789 f.push(7, 8, 0, 9);
2790 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
2791 break;
2792 case INTERSECT_QUAD_2:
2793 f.push(7, 8, 0, 12);
2794 f.push(10, 11, 9, 19);
2795 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
2796 break;
2797 case INTERSECT_QUAD_NO:
2798 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
2799 break;
2800 case INTERSECT_SELF_CUBIC:
2801 f.push(9, 10, 0, 11);
2802 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
2803 break;
2804 case INTERSECT_SELF_CUBIC_NO:
2805 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
2806 break;
2807 case INTERSECT_CUBIC_LINE:
2808 f.push(9, 10, 0, 11);
2809 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
2810 break;
2811 case INTERSECT_CUBIC_LINE_2:
2812 f.push(9, 10, 0, 14);
2813 f.push(12, 13, 11, 19);
2814 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
2815 break;
2816 case INTERSECT_CUBIC_LINE_3:
2817 f.push(9, 10, 0, 17);
2818 f.push(12, 13, 11, 22);
2819 f.push(15, 16, 14, 23);
2820 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
2821 break;
2822 case INTERSECT_CUBIC_QUAD_NO:
2823 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
2824 break;
2825 case INTERSECT_CUBIC_QUAD:
2826 f.push(9, 10, 0, 11);
2827 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
2828 break;
2829 case INTERSECT_CUBIC_QUAD_2:
2830 f.push(9, 10, 0, 14);
2831 f.push(12, 13, 11, 21);
2832 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
2833 break;
2834 case INTERSECT_CUBIC_QUAD_3:
2835 f.push(9, 10, 0, 17);
2836 f.push(12, 13, 11, 24);
2837 f.push(15, 16, 14, 25);
2838 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
2839 break;
2840 case INTERSECT_CUBIC_QUAD_4:
2841 f.push(9, 10, 0, 20);
2842 f.push(12, 13, 11, 27);
2843 f.push(15, 16, 14, 28);
2844 f.push(18, 19, 17, 29);
2845 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
2846 break;
2847 case INTERSECT_CUBIC_LINE_NO:
2848 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
2849 break;
2850 case INTERSECT_CUBIC:
2851 f.push(9, 10, 0, 11);
2852 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
2853 break;
2854 case INTERSECT_CUBIC_2:
2855 f.push(9, 10, 0, 14);
2856 f.push(12, 13, 11, 23);
2857 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
2858 break;
2859 case INTERSECT_CUBIC_3:
2860 f.push(9, 10, 0, 17);
2861 f.push(12, 13, 11, 26);
2862 f.push(15, 16, 14, 27);
2863 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
2864 break;
2865 case INTERSECT_CUBIC_4:
2866 f.push(9, 10, 0, 20);
2867 f.push(12, 13, 11, 29);
2868 f.push(15, 16, 14, 30);
2869 f.push(18, 19, 17, 31);
2870 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
2871 break;
2872 case INTERSECT_CUBIC_NO:
2873 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
2874 break;
2875 default:
2876 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
2877 throw "stop execution";
2878 }
2879 if (draw_intersection != 1) {
2880 var id = -1;
2881 var curve;
2882 switch (c1l) {
2883 case 4:
2884 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
2885 if (draw_id) {
2886 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
2887 id = idByCurve(test, curve, PATH_LINE);
2888 }
2889 break;
2890 case 6:
2891 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
2892 frags[c1s + 4], frags[c1s + 5]);
2893 if (draw_id) {
2894 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
2895 frags[c1s + 4], frags[c1s + 5]];
2896 id = idByCurve(test, curve, PATH_QUAD);
2897 }
2898 break;
2899 case 8:
2900 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
2901 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
2902 if (draw_id) {
2903 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
2904 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
2905 id = idByCurve(test, curve, PATH_CUBIC);
2906 }
2907 break;
2908 }
2909 if (id >= 0) {
2910 drawID(curve, id);
2911 }
2912 id = -1;
2913 switch (c2l) {
2914 case 0:
2915 break;
2916 case 4:
2917 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
2918 if (draw_id) {
2919 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
2920 id = idByCurve(test, curve, PATH_LINE);
2921 }
2922 break;
2923 case 6:
2924 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
2925 frags[c2s + 4], frags[c2s + 5]);
2926 if (draw_id) {
2927 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
2928 frags[c2s + 4], frags[c2s + 5]];
2929 id = idByCurve(test, curve, PATH_QUAD);
2930 }
2931 break;
2932 case 8:
2933 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
2934 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
2935 if (draw_id) {
2936 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
2937 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
2938 id = idByCurve(test, curve, PATH_CUBIC);
2939 }
2940 break;
2941 }
2942 if (id >= 0) {
2943 drawID(curve, id);
2944 }
2945 }
2946 if (collect_bounds) {
2947 break;
2948 }
2949 for (var idx = 0; idx < f.length; idx += 4) {
2950 if (draw_intersection != 3 || idx == lastSect - tIndex) {
2951 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
2952 }
2953 }
2954 if (!draw_intersectT) {
2955 break;
2956 }
2957 ctx.fillStyle = "red";
2958 for (var idx = 0; idx < f.length; idx += 4) {
2959 if (draw_intersection != 3 || idx == lastSect - tIndex) {
2960 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
2961 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
2962 }
2963 }
2964 break;
2965 case REC_TYPE_SORT:
2966 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
2967 continue;
2968 }
2969 ctx.lineWidth = 3;
2970 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
2971 focus_enabled = true;
2972 switch (fragType) {
2973 case SORT_UNARY:
2974 case SORT_BINARY:
2975 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
2976 drawCurve(curve);
2977 break;
2978 default:
2979 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
2980 throw "stop execution";
2981 }
2982 break;
2983 case REC_TYPE_MARK:
2984 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
2985 continue;
2986 }
2987 ctx.lineWidth = 3;
2988 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
2989 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
2990 focus_enabled = true;
2991 switch (fragType) {
2992 case MARK_LINE:
2993 case MARK_DONE_LINE:
2994 case MARK_UNSORTABLE_LINE:
2995 case MARK_SIMPLE_LINE:
2996 case MARK_SIMPLE_DONE_LINE:
2997 case MARK_DONE_UNARY_LINE:
2998 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
2999 frags[5], frags[9]);
3000 if (draw_id) {
3001 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3002 frags[5], frags[9]);
3003 }
3004 break;
3005 case MARK_QUAD:
3006 case MARK_DONE_QUAD:
3007 case MARK_UNSORTABLE_QUAD:
3008 case MARK_SIMPLE_QUAD:
3009 case MARK_SIMPLE_DONE_QUAD:
3010 case MARK_DONE_UNARY_QUAD:
3011 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3012 frags[5], frags[6], frags[7], frags[11]);
3013 if (draw_id) {
3014 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3015 frags[5], frags[6], frags[7], frags[11]);
3016 }
3017 break;
3018 case MARK_CUBIC:
3019 case MARK_DONE_CUBIC:
3020 case MARK_UNSORTABLE_CUBIC:
3021 case MARK_SIMPLE_CUBIC:
3022 case MARK_SIMPLE_DONE_CUBIC:
3023 case MARK_DONE_UNARY_CUBIC:
3024 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3025 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3026 if (draw_id) {
3027 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3028 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3029 }
3030 break;
3031 case MARK_ANGLE_LAST:
3032 // FIXME: ignored for now
3033 break;
3034 default:
3035 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3036 throw "stop execution";
3037 }
3038 break;
3039 default:
3040 continue;
3041 }
3042 }
3043 switch (recType) {
3044 case REC_TYPE_SORT:
3045 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3046 break;
3047 }
3048 var angles = []; // use tangent lines to describe arcs
3049 var windFrom = [];
3050 var windTo = [];
3051 var opp = [];
3052 var minXY = Number.MAX_VALUE;
3053 var partial;
3054 focus_enabled = true;
3055 var someUnsortable = false;
3056 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3057 var fragType = records[recordIndex];
3058 var frags = records[recordIndex + 1];
3059 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3060 (fragType == SORT_BINARY && frags[16]);
3061 someUnsortable |= unsortable;
3062 switch (fragType) {
3063 case SORT_UNARY:
3064 case SORT_BINARY:
3065 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3066 break;
3067 default:
3068 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3069 throw "stop execution";
3070 }
3071 var dx = boundsWidth(partial);
3072 var dy = boundsHeight(partial);
3073 minXY = Math.min(minXY, dx * dx + dy * dy);
3074 if (collect_bounds) {
3075 continue;
3076 }
3077 angles.push(tangent(partial));
3078 var from = frags[12];
3079 var to = frags[12];
3080 var sgn = frags[10];
3081 if (sgn < 0) {
3082 from -= frags[11];
3083 } else if (sgn > 0) {
3084 to -= frags[11];
3085 }
3086 windFrom.push(from + (unsortable ? "!" : ""));
3087 windTo.push(to + (unsortable ? "!" : ""));
3088 opp.push(fragType == SORT_BINARY);
3089 if (draw_sort == 1) {
3090 drawOrder(partial, frags[12]);
3091 } else {
3092 drawOrder(partial, (recordIndex / 2) + 1);
3093 }
3094 }
3095 var radius = Math.sqrt(minXY) / 2 * scale;
3096 radius = Math.min(50, radius);
3097 var scaledRadius = radius / scale;
3098 var centerX = partial[0];
3099 var centerY = partial[1];
3100 if (collect_bounds) {
3101 if (focus_enabled) {
3102 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
3103 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
3104 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
3105 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
3106 }
3107 break;
3108 }
3109 break;
3110 default:
3111 break;
3112 }
3113 }
3114 if (collect_bounds) {
3115 return;
3116 }
3117 if (draw_log && logStart >= 0) {
3118 ctx.font = "normal 10px Arial";
3119 ctx.textAlign = "left";
3120 ctx.beginPath();
3121 var top = screenHeight - 20 - (logRange + 2) * 10;
3122 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
3123 ctx.fillStyle = "white";
3124 ctx.fill();
3125 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3126 if (logStart > 0) {
3127 ctx.fillText(lines[logStart - 1], 50, top + 8);
3128 }
3129 ctx.fillStyle = "black";
3130 for (var idx = 0; idx < logRange; ++idx) {
3131 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
3132 }
3133 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3134 if (logStart + logRange < lines.length) {
3135 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
3136 }
3137 }
3138 if (draw_legend) {
3139 var pos = 0;
3140 var drawSomething = draw_add | draw_active | draw_sort | draw_mark;
3141 // drawBox(pos++, "yellow", "black", opLetter, true, '');
3142 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
3143 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
3144 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
3145 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
3146 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
3147 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
3148 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
3149 drawBox(pos++, "black", "white",
3150 (new Array('P', 'P1', 'P2', 'P'))[draw_path], draw_path != 0, pathKey);
3151 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
3152 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
3153 draw_computed != 0, computedKey);
3154 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
3155 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
3156 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
3157 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
3158 if (curve_t) {
3159 drawCurveTControl();
3160 }
3161 ctx.font = "normal 20px Arial";
3162 ctx.fillStyle = "rgba(0,0,0, 0.3)";
3163 ctx.textAlign = "right";
3164 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
3165 }
3166 if (draw_hints) {
3167 ctx.font = "normal 10px Arial";
3168 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3169 ctx.textAlign = "right";
3170 var y = 4;
3171 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
3172 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
3173 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
3174 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
3175 ctx.fillText("hodo : " + hodoKey, screenWidth - 10, pos * 50 + y++ * 10);
3176 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
3177 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
3178 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
3179 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
3180 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
3181 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
3182 }
3183}
3184
3185function drawBox(y, backC, foreC, str, enable, label) {
3186 ctx.beginPath();
3187 ctx.fillStyle = backC;
3188 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
3189 ctx.fill();
3190 ctx.font = "normal 16px Arial";
3191 ctx.fillStyle = foreC;
3192 ctx.textAlign = "center";
3193 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
3194 if (!enable) {
3195 ctx.fillStyle = "rgba(255,255,255, 0.5)";
3196 ctx.fill();
3197 }
3198 if (label != '') {
3199 ctx.font = "normal 9px Arial";
3200 ctx.fillStyle = "black";
3201 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
3202 }
3203}
3204
3205function drawCurveTControl() {
3206 ctx.lineWidth = 2;
3207 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
3208 ctx.beginPath();
3209 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
3210 ctx.stroke();
3211 var ty = 40 + curveT * (screenHeight - 80);
3212 ctx.beginPath();
3213 ctx.moveTo(screenWidth - 80, ty);
3214 ctx.lineTo(screenWidth - 85, ty - 5);
3215 ctx.lineTo(screenWidth - 85, ty + 5);
3216 ctx.lineTo(screenWidth - 80, ty);
3217 ctx.fillStyle = "rgba(0,0,0, 0.6)";
3218 ctx.fill();
3219 var num = curveT.toFixed(decimal_places);
3220 ctx.font = "normal 10px Arial";
3221 ctx.textAlign = "left";
3222 ctx.fillText(num, screenWidth - 78, ty);
3223}
3224
3225function ptInTControl() {
3226 var e = window.event;
3227 var tgt = e.target || e.srcElement;
3228 var left = tgt.offsetLeft;
3229 var top = tgt.offsetTop;
3230 var x = (e.clientX - left);
3231 var y = (e.clientY - top);
3232 if (x < screenWidth - 80 || x > screenWidth - 50) {
3233 return false;
3234 }
3235 if (y < 40 || y > screenHeight - 80) {
3236 return false;
3237 }
3238 curveT = (y - 40) / (screenHeight - 120);
3239 if (curveT < 0 || curveT > 1) {
3240 throw "stop execution";
3241 }
3242 return true;
3243}
3244
3245function drawTop() {
3246 if (tests[testIndex] == null) {
3247 var str = testDivs[testIndex].textContent;
3248 parse_all(str);
3249 var title = testDivs[testIndex].id.toString();
3250 testTitles[testIndex] = title;
3251 }
3252 init(tests[testIndex]);
3253 redraw();
3254}
3255
3256function redraw() {
3257 if (focus_on_selection) {
3258 collect_bounds = true;
3259 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3260 collect_bounds = false;
3261 if (focusXmin < focusXmax && focusYmin < focusYmax) {
3262 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
3263 }
3264 }
3265 ctx.beginPath();
3266 ctx.fillStyle = "white";
3267 ctx.rect(0, 0, screenWidth, screenHeight);
3268 ctx.fill();
3269 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
3270}
3271
3272function dumpCurvePartial(test, id, t0, t1) {
3273 var curve = curveByID(test, id);
3274 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
3275 console.log("id=" + id + " " + name + "=" + curveToString(curve)
3276 + " t0=" + t0 + " t1=" + t1
3277 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
3278}
3279
3280function dumpAngleTest(test, id, t0, t1) {
3281 var curve = curveByID(test, id);
3282 console.log(" { {" + curveToString(curve) + "}, "
3283 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
3284}
3285
3286function dumpLogToConsole() {
3287 if (logStart < 0) {
3288 return;
3289 }
3290 var test = tests[testIndex];
3291 var recType = REC_TYPE_UNKNOWN;
3292 var records;
3293 for (var index = 0; index < test.length; index += 3) {
3294 var lastLineNo = test[index + 1];
3295 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
3296 recType = test[index];
3297 records = test[index + 2];
3298 break;
3299 }
3300 }
3301 if (recType == REC_TYPE_UNKNOWN) {
3302 return;
3303 }
3304 var lines = testLines[testIndex];
3305 for (var idx = 0; idx < logRange; ++idx) {
3306 var line = lines[logStart + idx];
3307 console.log(line);
3308 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3309 var fragType = records[recordIndex];
3310 var frags = records[recordIndex + 1];
3311 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
3312 dumpCurvePartial(test, frags[0], frags[3], frags[4]);
3313 dumpCurvePartial(test, frags[5], frags[8], frags[9]);
3314 dumpCurvePartial(test, frags[10], frags[13], frags[14]);
3315 console.log("\nstatic IntersectData intersectDataSet[] = {");
3316 dumpAngleTest(test, frags[0], frags[3], frags[4]);
3317 dumpAngleTest(test, frags[5], frags[8], frags[9]);
3318 dumpAngleTest(test, frags[10], frags[13], frags[14]);
3319 console.log("};");
3320 } else if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER2) {
3321 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
3322 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
3323 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
3324 console.log("\nstatic IntersectData intersectDataSet[] = { //");
3325 dumpAngleTest(test, frags[0], frags[4], frags[5]);
3326 dumpAngleTest(test, frags[6], frags[10], frags[11]);
3327 dumpAngleTest(test, frags[12], frags[16], frags[17]);
3328 console.log("}; //");
3329 }
3330 }
3331 }
3332}
3333
3334var activeKey = 'a';
3335var pathKey = 'b';
3336var pathBackKey = 'B';
3337var centerKey = 'c';
3338var addKey = 'd';
3339var deriviativesKey = 'f';
3340var angleKey = 'g';
3341var angleBackKey = 'G';
3342var hodoKey = 'h';
3343var intersectionKey = 'i';
3344var intersectionBackKey = 'I';
3345var sequenceKey = 'j';
3346var midpointKey = 'k';
3347var logKey = 'l';
3348var logToConsoleKey = 'L';
3349var markKey = 'm';
3350var sortKey = 'o';
3351var opKey = 'p';
3352var opBackKey = 'P';
3353var computedKey = 'q';
3354var computedBackKey = 'Q';
3355var stepKey = 's';
3356var stepBackKey = 'S';
3357var intersectTKey = 't';
3358var curveTKey = 'u';
3359var controlLinesBackKey = 'V';
3360var controlLinesKey = 'v';
3361var ptsKey = 'x';
3362var xyKey = 'y';
3363var logCurvesKey = 'z';
3364var focusKey = '`';
3365var idKey = '.';
3366var retinaKey = '\\';
3367
3368function doKeyPress(evt) {
3369 var char = String.fromCharCode(evt.charCode);
3370 var focusWasOn = false;
3371 switch (char) {
3372 case '0':
3373 case '1':
3374 case '2':
3375 case '3':
3376 case '4':
3377 case '5':
3378 case '6':
3379 case '7':
3380 case '8':
3381 case '9':
3382 decimal_places = char - '0';
3383 redraw();
3384 break;
3385 case activeKey:
3386 draw_active ^= true;
3387 redraw();
3388 break;
3389 case addKey:
3390 draw_add ^= true;
3391 redraw();
3392 break;
3393 case angleKey:
3394 draw_angle = (draw_angle + 1) % 3;
3395 redraw();
3396 break;
3397 case angleBackKey:
3398 draw_angle = (draw_angle + 2) % 3;
3399 redraw();
3400 break;
3401 case centerKey:
3402 setScale(xmin, xmax, ymin, ymax);
3403 redraw();
3404 break;
3405 case controlLinesBackKey:
3406 control_lines = (control_lines + 3) % 4;
3407 redraw();
3408 break;
3409 case controlLinesKey:
3410 control_lines = (control_lines + 1) % 4;
3411 redraw();
3412 break;
3413 case computedBackKey:
3414 draw_computed = (draw_computed + 5) % 6;
3415 redraw();
3416 break;
3417 case computedKey:
3418 draw_computed = (draw_computed + 1) % 6;
3419 redraw();
3420 break;
3421 case curveTKey:
3422 curve_t ^= true;
3423 if (curve_t) {
3424 draw_legend = true;
3425 }
3426 redraw();
3427 break;
3428 case deriviativesKey:
3429 draw_deriviatives = (draw_deriviatives + 1) % 3;
3430 redraw();
3431 break;
3432 case focusKey:
3433 focus_on_selection ^= true;
3434 setScale(xmin, xmax, ymin, ymax);
3435 redraw();
3436 break;
3437 case hodoKey:
3438 draw_hodo = (draw_hodo + 1) % 4;
3439 redraw();
3440 break;
3441 case idKey:
3442 draw_id ^= true;
3443 redraw();
3444 break;
3445 case intersectionBackKey:
3446 draw_intersection = (draw_intersection + 3) % 4;
3447 redraw();
3448 break;
3449 case intersectionKey:
3450 draw_intersection = (draw_intersection + 1) % 4;
3451 redraw();
3452 break;
3453 case intersectTKey:
3454 draw_intersectT ^= true;
3455 redraw();
3456 break;
3457 case logCurvesKey:
3458 logCurves(tests[testIndex]);
3459 break;
3460 case logKey:
3461 draw_log ^= true;
3462 redraw();
3463 break;
3464 case logToConsoleKey:
3465 if (draw_log) {
3466 dumpLogToConsole();
3467 }
3468 break;
3469 case markKey:
3470 draw_mark ^= true;
3471 redraw();
3472 break;
3473 case midpointKey:
3474 draw_midpoint ^= true;
3475 redraw();
3476 break;
3477 case opKey:
3478 draw_op = (draw_op + 1) % 3;
3479 redraw();
3480 break;
3481 case opBackKey:
3482 draw_op = (draw_op + 2) % 3;
3483 redraw();
3484 break;
3485 case pathKey:
3486 draw_path = (draw_path + 1) % 4;
3487 redraw();
3488 break;
3489 case pathBackKey:
3490 draw_path = (draw_path + 3) % 4;
3491 redraw();
3492 break;
3493 case ptsKey:
3494 pt_labels = (pt_labels + 1) % 3;
3495 redraw();
3496 break;
3497 case retinaKey:
3498 retina_scale ^= true;
3499 drawTop();
3500 break;
3501 case sequenceKey:
3502 draw_sequence ^= true;
3503 redraw();
3504 break;
3505 case sortKey:
3506 draw_sort = (draw_sort + 1) % 3;
3507 drawTop();
3508 break;
3509 case stepKey:
3510 step_limit++;
3511 if (step_limit > stepMax) {
3512 step_limit = stepMax;
3513 }
3514 redraw();
3515 break;
3516 case stepBackKey:
3517 step_limit--;
3518 if (step_limit < 0) {
3519 step_limit = 0;
3520 }
3521 redraw();
3522 break;
3523 case xyKey:
3524 debug_xy = (debug_xy + 1) % 3;
3525 redraw();
3526 break;
3527 case '-':
3528 focusWasOn = focus_on_selection;
3529 if (focusWasOn) {
3530 focus_on_selection = false;
3531 scale /= 1.2;
3532 } else {
3533 scale /= 2;
3534 calcLeftTop();
3535 }
3536 redraw();
3537 focus_on_selection = focusWasOn;
3538 break;
3539 case '=':
3540 case '+':
3541 focusWasOn = focus_on_selection;
3542 if (focusWasOn) {
3543 focus_on_selection = false;
3544 scale *= 1.2;
3545 } else {
3546 scale *= 2;
3547 calcLeftTop();
3548 }
3549 redraw();
3550 focus_on_selection = focusWasOn;
3551 break;
3552 case '?':
3553 draw_hints ^= true;
3554 if (draw_hints && !draw_legend) {
3555 draw_legend = true;
3556 }
3557 redraw();
3558 break;
3559 case '/':
3560 draw_legend ^= true;
3561 redraw();
3562 break;
3563 }
3564}
3565
3566function doKeyDown(evt) {
3567 var char = evt.keyCode;
3568 var preventDefault = false;
3569 switch (char) {
3570 case 37: // left arrow
3571 if (evt.shiftKey) {
3572 testIndex -= 9;
3573 }
3574 if (--testIndex < 0)
3575 testIndex = tests.length - 1;
3576 drawTop();
3577 preventDefault = true;
3578 break;
3579 case 39: // right arrow
3580 if (evt.shiftKey) {
3581 testIndex += 9;
3582 }
3583 if (++testIndex >= tests.length)
3584 testIndex = 0;
3585 drawTop();
3586 preventDefault = true;
3587 break;
3588 }
3589 if (preventDefault) {
3590 evt.preventDefault();
3591 return false;
3592 }
3593 return true;
3594}
3595
3596(function() {
3597 var hidden = "hidden";
3598
3599 // Standards:
3600 if (hidden in document)
3601 document.addEventListener("visibilitychange", onchange);
3602 else if ((hidden = "mozHidden") in document)
3603 document.addEventListener("mozvisibilitychange", onchange);
3604 else if ((hidden = "webkitHidden") in document)
3605 document.addEventListener("webkitvisibilitychange", onchange);
3606 else if ((hidden = "msHidden") in document)
3607 document.addEventListener("msvisibilitychange", onchange);
3608 // IE 9 and lower:
3609 else if ('onfocusin' in document)
3610 document.onfocusin = document.onfocusout = onchange;
3611 // All others:
3612 else
3613 window.onpageshow = window.onpagehide
3614 = window.onfocus = window.onblur = onchange;
3615
3616 function onchange (evt) {
3617 var v = 'visible', h = 'hidden',
3618 evtMap = {
3619 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
3620 };
3621
3622 evt = evt || window.event;
3623 if (evt.type in evtMap)
3624 document.body.className = evtMap[evt.type];
3625 else
3626 document.body.className = this[hidden] ? "hidden" : "visible";
3627 }
3628})();
3629
3630function calcXY() {
3631 var e = window.event;
3632 var tgt = e.target || e.srcElement;
3633 var left = tgt.offsetLeft;
3634 var top = tgt.offsetTop;
3635 mouseX = (e.clientX - left) / scale + srcLeft;
3636 mouseY = (e.clientY - top) / scale + srcTop;
3637}
3638
3639function calcLeftTop() {
3640 srcLeft = mouseX - screenWidth / 2 / scale;
3641 srcTop = mouseY - screenHeight / 2 / scale;
3642}
3643
3644var disableClick = false;
3645
3646function handleMouseClick() {
3647 if (disableClick) {
3648 return;
3649 }
3650 if (!curve_t || !ptInTControl()) {
3651 calcXY();
3652 calcLeftTop();
3653 }
3654 redraw();
3655// if (!curve_t || !ptInTControl()) {
3656// mouseX = screenWidth / 2 / scale + srcLeft;
3657// mouseY = screenHeight / 2 / scale + srcTop;
3658// }
3659}
3660
3661function handleMouseOver() {
3662 calcXY();
3663 if (debug_xy != 2) {
3664 return;
3665 }
3666 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
3667 ctx.beginPath();
3668 ctx.rect(300,100,num.length * 6,10);
3669 ctx.fillStyle="white";
3670 ctx.fill();
3671 ctx.font = "normal 10px Arial";
3672 ctx.fillStyle="black";
3673 ctx.textAlign = "left";
3674 ctx.fillText(num, 300, 108);
3675}
3676
3677function start() {
3678 for (var i = 0; i < testDivs.length; ++i) {
3679 tests[i] = null;
3680 }
3681 testIndex = 0;
3682 drawTop();
3683 window.addEventListener('keypress', doKeyPress, true);
3684 window.addEventListener('keydown', doKeyDown, true);
3685 window.onresize = function() {
3686 drawTop();
3687 }
3688 /*
3689 window.onpagehide = function() {
3690 disableClick = true;
3691 }
3692 */
3693 window.onpageshow = function () {
3694 disableClick = false;
3695 }
3696}
3697
3698</script>
3699</head>
3700
3701<body onLoad="start();">
3702<canvas id="canvas" width="750" height="500"
3703 onmousemove="handleMouseOver()"
3704 onclick="handleMouseClick()"
3705 ></canvas >
3706</body>
3707</html>