Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
24ea0f0d
Commit
24ea0f0d
authored
Oct 26, 2015
by
Kris Giesing
Committed by
kgiesing
Nov 02, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move velocity tracker to dart
parent
56b25763
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
5001 additions
and
9 deletions
+5001
-9
gestures.dart
packages/flutter/lib/gestures.dart
+2
-0
drag.dart
packages/flutter/lib/src/gestures/drag.dart
+8
-9
lsq_solver.dart
packages/flutter/lib/src/gestures/lsq_solver.dart
+190
-0
velocity_tracker.dart
packages/flutter/lib/src/gestures/velocity_tracker.dart
+234
-0
event_recorder.dart
packages/flutter/lib/src/widgets/event_recorder.dart
+68
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-0
README.md
packages/unit/benchmark/README.md
+13
-0
velocity_tracker_bench.dart
packages/unit/benchmark/gestures/velocity_tracker_bench.dart
+64
-0
velocity_tracker_data.dart
packages/unit/benchmark/gestures/velocity_tracker_data.dart
+2144
-0
lsq_solver_test.dart
packages/unit/test/gestures/lsq_solver_test.dart
+69
-0
velocity_tracker_data.dart
packages/unit/test/gestures/velocity_tracker_data.dart
+2144
-0
velocity_tracker_test.dart
packages/unit/test/gestures/velocity_tracker_test.dart
+64
-0
No files found.
packages/flutter/lib/gestures.dart
View file @
24ea0f0d
...
@@ -10,8 +10,10 @@ export 'src/gestures/constants.dart';
...
@@ -10,8 +10,10 @@ export 'src/gestures/constants.dart';
export
'src/gestures/drag.dart'
;
export
'src/gestures/drag.dart'
;
export
'src/gestures/events.dart'
;
export
'src/gestures/events.dart'
;
export
'src/gestures/long_press.dart'
;
export
'src/gestures/long_press.dart'
;
export
'src/gestures/lsq_solver.dart'
;
export
'src/gestures/pointer_router.dart'
;
export
'src/gestures/pointer_router.dart'
;
export
'src/gestures/recognizer.dart'
;
export
'src/gestures/recognizer.dart'
;
export
'src/gestures/scale.dart'
;
export
'src/gestures/scale.dart'
;
export
'src/gestures/show_press.dart'
;
export
'src/gestures/show_press.dart'
;
export
'src/gestures/tap.dart'
;
export
'src/gestures/tap.dart'
;
export
'src/gestures/velocity_tracker.dart'
;
packages/flutter/lib/src/gestures/drag.dart
View file @
24ea0f0d
...
@@ -8,6 +8,7 @@ import 'arena.dart';
...
@@ -8,6 +8,7 @@ import 'arena.dart';
import
'recognizer.dart'
;
import
'recognizer.dart'
;
import
'constants.dart'
;
import
'constants.dart'
;
import
'events.dart'
;
import
'events.dart'
;
import
'velocity_tracker.dart'
;
enum
DragState
{
enum
DragState
{
ready
,
ready
,
...
@@ -25,9 +26,7 @@ typedef void GesturePanEndCallback(ui.Offset velocity);
...
@@ -25,9 +26,7 @@ typedef void GesturePanEndCallback(ui.Offset velocity);
typedef
void
_GesturePolymorphicUpdateCallback
<
T
>(
T
delta
);
typedef
void
_GesturePolymorphicUpdateCallback
<
T
>(
T
delta
);
int
_eventTime
(
PointerInputEvent
event
)
=>
(
event
.
timeStamp
*
1000.0
).
toInt
();
// microseconds
bool
_isFlingGesture
(
GestureVelocity
velocity
)
{
bool
_isFlingGesture
(
ui
.
GestureVelocity
velocity
)
{
double
velocitySquared
=
velocity
.
x
*
velocity
.
x
+
velocity
.
y
*
velocity
.
y
;
double
velocitySquared
=
velocity
.
x
*
velocity
.
x
+
velocity
.
y
*
velocity
.
y
;
return
velocity
.
isValid
&&
return
velocity
.
isValid
&&
velocitySquared
>
kMinFlingVelocity
*
kMinFlingVelocity
&&
velocitySquared
>
kMinFlingVelocity
*
kMinFlingVelocity
&&
...
@@ -50,11 +49,11 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecogniz
...
@@ -50,11 +49,11 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecogniz
T
_getDragDelta
(
PointerInputEvent
event
);
T
_getDragDelta
(
PointerInputEvent
event
);
bool
get
_hasSufficientPendingDragDeltaToAccept
;
bool
get
_hasSufficientPendingDragDeltaToAccept
;
Map
<
int
,
ui
.
VelocityTracker
>
_velocityTrackers
=
new
Map
<
int
,
ui
.
VelocityTracker
>();
Map
<
int
,
VelocityTracker
>
_velocityTrackers
=
new
Map
<
int
,
VelocityTracker
>();
void
addPointer
(
PointerInputEvent
event
)
{
void
addPointer
(
PointerInputEvent
event
)
{
startTrackingPointer
(
event
.
pointer
);
startTrackingPointer
(
event
.
pointer
);
_velocityTrackers
[
event
.
pointer
]
=
new
ui
.
VelocityTracker
();
_velocityTrackers
[
event
.
pointer
]
=
new
VelocityTracker
();
if
(
_state
==
DragState
.
ready
)
{
if
(
_state
==
DragState
.
ready
)
{
_state
=
DragState
.
possible
;
_state
=
DragState
.
possible
;
_initialPosition
=
event
.
position
;
_initialPosition
=
event
.
position
;
...
@@ -65,9 +64,9 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecogniz
...
@@ -65,9 +64,9 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecogniz
void
handleEvent
(
PointerInputEvent
event
)
{
void
handleEvent
(
PointerInputEvent
event
)
{
assert
(
_state
!=
DragState
.
ready
);
assert
(
_state
!=
DragState
.
ready
);
if
(
event
.
type
==
'pointermove'
)
{
if
(
event
.
type
==
'pointermove'
)
{
ui
.
VelocityTracker
tracker
=
_velocityTrackers
[
event
.
pointer
];
VelocityTracker
tracker
=
_velocityTrackers
[
event
.
pointer
];
assert
(
tracker
!=
null
);
assert
(
tracker
!=
null
);
tracker
.
addPosition
(
_eventTime
(
event
)
,
event
.
x
,
event
.
y
);
tracker
.
addPosition
(
event
.
timeStamp
,
event
.
x
,
event
.
y
);
T
delta
=
_getDragDelta
(
event
);
T
delta
=
_getDragDelta
(
event
);
if
(
_state
==
DragState
.
accepted
)
{
if
(
_state
==
DragState
.
accepted
)
{
if
(
onUpdate
!=
null
)
if
(
onUpdate
!=
null
)
...
@@ -102,10 +101,10 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecogniz
...
@@ -102,10 +101,10 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecogniz
bool
wasAccepted
=
(
_state
==
DragState
.
accepted
);
bool
wasAccepted
=
(
_state
==
DragState
.
accepted
);
_state
=
DragState
.
ready
;
_state
=
DragState
.
ready
;
if
(
wasAccepted
&&
onEnd
!=
null
)
{
if
(
wasAccepted
&&
onEnd
!=
null
)
{
ui
.
VelocityTracker
tracker
=
_velocityTrackers
[
pointer
];
VelocityTracker
tracker
=
_velocityTrackers
[
pointer
];
assert
(
tracker
!=
null
);
assert
(
tracker
!=
null
);
ui
.
GestureVelocity
gestureVelocity
=
tracker
.
getVelocity
();
GestureVelocity
gestureVelocity
=
tracker
.
getVelocity
();
ui
.
Offset
velocity
=
ui
.
Offset
.
zero
;
ui
.
Offset
velocity
=
ui
.
Offset
.
zero
;
if
(
_isFlingGesture
(
gestureVelocity
))
if
(
_isFlingGesture
(
gestureVelocity
))
velocity
=
new
ui
.
Offset
(
gestureVelocity
.
x
,
gestureVelocity
.
y
);
velocity
=
new
ui
.
Offset
(
gestureVelocity
.
x
,
gestureVelocity
.
y
);
...
...
packages/flutter/lib/src/gestures/lsq_solver.dart
0 → 100644
View file @
24ea0f0d
import
"dart:math"
as
math
;
import
"dart:typed_data"
;
class
Vector
{
Vector
(
int
size
)
:
_offset
=
0
,
_length
=
size
,
_elem
=
new
Float64List
(
size
);
Vector
.
fromValues
(
List
<
double
>
values
)
:
_offset
=
0
,
_length
=
values
.
length
,
_elem
=
values
;
Vector
.
fromVOL
(
List
<
double
>
values
,
int
offset
,
int
length
)
:
_offset
=
offset
,
_length
=
length
,
_elem
=
values
;
int
get
length
=>
_length
;
operator
[](
int
i
)
=>
_elem
[
i
+
_offset
];
operator
[]=(
int
i
,
double
value
)
=>
_elem
[
i
+
_offset
]
=
value
;
operator
*(
Vector
a
)
{
double
result
=
0.0
;
for
(
int
i
=
0
;
i
<
_length
;
i
++)
{
result
+=
this
[
i
]
*
a
[
i
];
}
return
result
;
}
double
norm
()
=>
math
.
sqrt
(
this
*
this
);
String
toString
()
{
String
result
=
""
;
for
(
int
i
=
0
;
i
<
_length
;
i
++)
{
if
(
i
>
0
)
result
+=
", "
;
result
+=
this
[
i
].
toString
();
}
return
result
;
}
final
int
_offset
;
final
int
_length
;
final
List
<
double
>
_elem
;
}
class
Matrix
{
Matrix
(
int
rows
,
int
cols
)
:
_rows
=
rows
,
_cols
=
cols
,
_elem
=
new
Float64List
(
rows
*
cols
);
double
get
(
int
row
,
int
col
)
=>
_elem
[
row
*
_cols
+
col
];
void
set
(
int
row
,
int
col
,
double
value
)
{
_elem
[
row
*
_cols
+
col
]
=
value
;
}
Vector
getRow
(
int
row
)
=>
new
Vector
.
fromVOL
(
_elem
,
row
*
_cols
,
_cols
);
String
toString
()
{
String
result
=
""
;
for
(
int
i
=
0
;
i
<
_rows
;
i
++)
{
if
(
i
>
0
)
result
+=
"; "
;
for
(
int
j
=
0
;
j
<
_cols
;
j
++)
{
if
(
j
>
0
)
result
+=
", "
;
result
+=
get
(
i
,
j
).
toString
();
}
}
return
result
;
}
final
int
_rows
;
final
int
_cols
;
final
List
<
double
>
_elem
;
}
class
PolynomialFit
{
PolynomialFit
(
int
degree
)
:
coefficients
=
new
Float64List
(
degree
+
1
);
final
List
<
double
>
coefficients
;
double
confidence
;
}
class
LeastSquaresSolver
{
LeastSquaresSolver
(
this
.
x
,
this
.
y
,
this
.
w
)
{
assert
(
x
.
length
==
y
.
length
);
assert
(
y
.
length
==
w
.
length
);
}
final
List
<
double
>
x
;
final
List
<
double
>
y
;
final
List
<
double
>
w
;
PolynomialFit
solve
(
int
degree
)
{
if
(
degree
>
x
.
length
)
// not enough data to fit a curve
return
null
;
PolynomialFit
result
=
new
PolynomialFit
(
degree
);
// Shorthands for the purpose of notation equivalence to original C++ code
final
int
m
=
x
.
length
;
final
int
n
=
degree
+
1
;
final
List
<
double
>
out_b
=
result
.
coefficients
;
// Expand the X vector to a matrix A, pre-multiplied by the weights.
Matrix
a
=
new
Matrix
(
n
,
m
);
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
a
.
set
(
0
,
h
,
w
[
h
]);
for
(
int
i
=
1
;
i
<
n
;
i
++)
{
a
.
set
(
i
,
h
,
a
.
get
(
i
-
1
,
h
)
*
x
[
h
]);
}
}
// Apply the Gram-Schmidt process to A to obtain its QR decomposition.
// Orthonormal basis, column-major ordVectorer.
Matrix
q
=
new
Matrix
(
n
,
m
);
// Upper triangular matrix, row-major order.
Matrix
r
=
new
Matrix
(
n
,
n
);
for
(
int
j
=
0
;
j
<
n
;
j
++)
{
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
q
.
set
(
j
,
h
,
a
.
get
(
j
,
h
));
}
for
(
int
i
=
0
;
i
<
j
;
i
++)
{
double
dot
=
q
.
getRow
(
j
)*
q
.
getRow
(
i
);
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
q
.
set
(
j
,
h
,
q
.
get
(
j
,
h
)
-
dot
*
q
.
get
(
i
,
h
));
}
}
double
norm
=
q
.
getRow
(
j
).
norm
();
if
(
norm
<
0.000001
)
{
// vectors are linearly dependent or zero so no solution
return
null
;
}
double
invNorm
=
1.0
/
norm
;
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
q
.
set
(
j
,
h
,
q
.
get
(
j
,
h
)
*
invNorm
);
}
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
r
.
set
(
j
,
i
,
i
<
j
?
0.0
:
q
.
getRow
(
j
)*
a
.
getRow
(
i
));
}
}
// Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
// We just work from bottom-right to top-left calculating B's coefficients.
Vector
wy
=
new
Vector
(
m
);
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
wy
[
h
]
=
y
[
h
]
*
w
[
h
];
}
for
(
int
i
=
n
;
i
--
!=
0
;)
{
out_b
[
i
]
=
q
.
getRow
(
i
)
*
wy
;
for
(
int
j
=
n
-
1
;
j
>
i
;
j
--)
{
out_b
[
i
]
-=
r
.
get
(
i
,
j
)
*
out_b
[
j
];
}
out_b
[
i
]
/=
r
.
get
(
i
,
i
);
}
// Calculate the coefficient of determination as 1 - (SSerr / SStot) where
// SSerr is the residual sum of squares (variance of the error),
// and SStot is the total sum of squares (variance of the data) where each
// has been weighted.
double
ymean
=
0.0
;
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
ymean
+=
y
[
h
];
}
ymean
/=
m
;
double
sserr
=
0.0
;
double
sstot
=
0.0
;
for
(
int
h
=
0
;
h
<
m
;
h
++)
{
double
err
=
y
[
h
]
-
out_b
[
0
];
double
term
=
1.0
;
for
(
int
i
=
1
;
i
<
n
;
i
++)
{
term
*=
x
[
h
];
err
-=
term
*
out_b
[
i
];
}
sserr
+=
w
[
h
]
*
w
[
h
]
*
err
*
err
;
double
v
=
y
[
h
]
-
ymean
;
sstot
+=
w
[
h
]
*
w
[
h
]
*
v
*
v
;
}
double
det
=
sstot
>
0.000001
?
1.0
-
(
sserr
/
sstot
)
:
1.0
;
result
.
confidence
=
det
;
return
result
;
}
}
packages/flutter/lib/src/gestures/velocity_tracker.dart
0 → 100644
View file @
24ea0f0d
import
'dart:ui'
as
ui
;
import
'lsq_solver.dart'
;
class
GestureVelocity
{
GestureVelocity
({
this
.
isValid
:
false
,
this
.
x
:
0.0
,
this
.
y
:
0.0
});
final
bool
isValid
;
final
double
x
;
final
double
y
;
}
class
Estimator
{
int
degree
;
double
time
;
List
<
double
>
xcoeff
;
List
<
double
>
ycoeff
;
double
confidence
;
String
toString
()
{
String
result
=
"Estimator(degree: "
+
degree
.
toString
();
result
+=
", time: "
+
time
.
toString
();
result
+=
", confidence: "
+
confidence
.
toString
();
result
+=
", xcoeff: "
+
(
new
Vector
.
fromValues
(
xcoeff
)).
toString
();
result
+=
", ycoeff: "
+
(
new
Vector
.
fromValues
(
ycoeff
)).
toString
();
return
result
;
}
}
abstract
class
VelocityTrackerStrategy
{
void
addMovement
(
double
timeStamp
,
double
x
,
double
y
);
bool
getEstimator
(
Estimator
estimator
);
void
clear
();
}
enum
Weighting
{
WEIGHTING_NONE
,
WEIGHTING_DELTA
,
WEIGHTING_CENTRAL
,
WEIGHTING_RECENT
}
class
Movement
{
double
event_time
=
0.0
;
ui
.
Point
position
=
ui
.
Point
.
origin
;
}
class
LeastSquaresVelocityTrackerStrategy
extends
VelocityTrackerStrategy
{
static
const
int
kHistorySize
=
20
;
static
const
int
kHorizonMS
=
100
;
LeastSquaresVelocityTrackerStrategy
(
this
.
degree
,
this
.
weighting
)
:
_index
=
0
,
_movements
=
new
List
<
Movement
>(
kHistorySize
);
final
int
degree
;
final
Weighting
weighting
;
final
List
<
Movement
>
_movements
;
int
_index
;
void
addMovement
(
double
timeStamp
,
double
x
,
double
y
)
{
if
(++
_index
==
kHistorySize
)
_index
=
0
;
Movement
movement
=
_getMovement
(
_index
);
movement
.
event_time
=
timeStamp
;
movement
.
position
=
new
ui
.
Point
(
x
,
y
);
}
bool
getEstimator
(
Estimator
estimator
)
{
// Iterate over movement samples in reverse time order and collect samples.
List
<
double
>
x
=
new
List
<
double
>();
List
<
double
>
y
=
new
List
<
double
>();
List
<
double
>
w
=
new
List
<
double
>();
List
<
double
>
time
=
new
List
<
double
>();
int
m
=
0
;
int
index
=
_index
;
Movement
newest_movement
=
_getMovement
(
index
);
do
{
Movement
movement
=
_getMovement
(
index
);
double
age
=
newest_movement
.
event_time
-
movement
.
event_time
;
if
(
age
>
kHorizonMS
)
break
;
ui
.
Point
position
=
movement
.
position
;
x
.
add
(
position
.
x
);
y
.
add
(
position
.
y
);
w
.
add
(
_chooseWeight
(
index
));
time
.
add
(-
age
);
index
=
(
index
==
0
?
kHistorySize
:
index
)
-
1
;
}
while
(++
m
<
kHistorySize
);
if
(
m
==
0
)
return
false
;
// no data
// Calculate a least squares polynomial fit.
int
n
=
degree
;
if
(
n
>
m
-
1
)
n
=
m
-
1
;
if
(
n
>=
1
)
{
LeastSquaresSolver
xSolver
=
new
LeastSquaresSolver
(
time
,
x
,
w
);
PolynomialFit
xFit
=
xSolver
.
solve
(
n
);
if
(
xFit
!=
null
)
{
LeastSquaresSolver
ySolver
=
new
LeastSquaresSolver
(
time
,
y
,
w
);
PolynomialFit
yFit
=
ySolver
.
solve
(
n
);
if
(
yFit
!=
null
)
{
estimator
.
xcoeff
=
xFit
.
coefficients
;
estimator
.
ycoeff
=
yFit
.
coefficients
;
estimator
.
time
=
newest_movement
.
event_time
;
estimator
.
degree
=
n
;
estimator
.
confidence
=
xFit
.
confidence
*
yFit
.
confidence
;
return
true
;
}
}
}
// No velocity data available for this pointer, but we do have its current
// position.
estimator
.
xcoeff
=
[
x
[
0
]
];
estimator
.
ycoeff
=
[
y
[
0
]
];
estimator
.
time
=
newest_movement
.
event_time
;
estimator
.
degree
=
0
;
estimator
.
confidence
=
1.0
;
return
true
;
}
void
clear
()
{
_index
=
-
1
;
}
double
_chooseWeight
(
int
index
)
{
switch
(
weighting
)
{
case
Weighting
.
WEIGHTING_DELTA
:
// Weight points based on how much time elapsed between them and the next
// point so that points that "cover" a shorter time span are weighed less.
// delta 0ms: 0.5
// delta 10ms: 1.0
if
(
index
==
_index
)
{
return
1.0
;
}
int
next_index
=
(
index
+
1
)
%
kHistorySize
;
double
delta_millis
=
_movements
[
next_index
].
event_time
-
_movements
[
index
].
event_time
;
if
(
delta_millis
<
0
)
return
0.5
;
if
(
delta_millis
<
10
)
return
0.5
+
delta_millis
*
0.05
;
return
1.0
;
case
Weighting
.
WEIGHTING_CENTRAL
:
// Weight points based on their age, weighing very recent and very old
// points less.
// age 0ms: 0.5
// age 10ms: 1.0
// age 50ms: 1.0
// age 60ms: 0.5
double
age_millis
=
_movements
[
_index
].
event_time
-
_movements
[
index
].
event_time
;
if
(
age_millis
<
0
)
return
0.5
;
if
(
age_millis
<
10
)
return
0.5
+
age_millis
*
0.05
;
if
(
age_millis
<
50
)
return
1.0
;
if
(
age_millis
<
60
)
return
0.5
+
(
60
-
age_millis
)
*
0.05
;
return
0.5
;
case
Weighting
.
WEIGHTING_RECENT
:
// Weight points based on their age, weighing older points less.
// age 0ms: 1.0
// age 50ms: 1.0
// age 100ms: 0.5
double
age_millis
=
_movements
[
_index
].
event_time
-
_movements
[
index
].
event_time
;
if
(
age_millis
<
50
)
{
return
1.0
;
}
if
(
age_millis
<
100
)
{
return
0.5
+
(
100
-
age_millis
)
*
0.01
;
}
return
0.5
;
case
Weighting
.
WEIGHTING_NONE
:
default
:
return
1.0
;
}
}
Movement
_getMovement
(
int
i
)
{
Movement
result
=
_movements
[
i
];
if
(
result
==
null
)
{
result
=
new
Movement
();
_movements
[
i
]
=
result
;
}
return
result
;
}
}
class
VelocityTracker
{
static
const
int
kAssumePointerMoveStoppedTimeMs
=
40
;
VelocityTracker
()
:
_lastTimeStamp
=
0.0
,
_strategy
=
_createStrategy
();
double
_lastTimeStamp
;
VelocityTrackerStrategy
_strategy
;
void
addPosition
(
double
timeStamp
,
double
x
,
double
y
)
{
if
((
timeStamp
-
_lastTimeStamp
)
>=
kAssumePointerMoveStoppedTimeMs
)
_strategy
.
clear
();
_lastTimeStamp
=
timeStamp
;
_strategy
.
addMovement
(
timeStamp
,
x
,
y
);
}
GestureVelocity
getVelocity
()
{
Estimator
estimator
=
new
Estimator
();
if
(
_strategy
.
getEstimator
(
estimator
)
&&
estimator
.
degree
>=
1
)
{
// convert from pixels/ms to pixels/s
return
new
GestureVelocity
(
isValid:
true
,
x:
estimator
.
xcoeff
[
1
]*
1000
,
y:
estimator
.
ycoeff
[
1
]*
1000
);
}
return
new
GestureVelocity
(
isValid:
false
,
x:
0.0
,
y:
0.0
);
}
static
VelocityTrackerStrategy
_createStrategy
()
{
return
new
LeastSquaresVelocityTrackerStrategy
(
2
,
Weighting
.
WEIGHTING_NONE
);
}
}
packages/flutter/lib/src/widgets/event_recorder.dart
0 → 100644
View file @
24ea0f0d
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'basic.dart'
;
import
'framework.dart'
;
enum
EventRecorderMode
{
stop
,
record
}
typedef
void
EventsReady
(
List
<
PointerInputEvent
>
events
);
class
EventRecorder
extends
StatefulComponent
{
EventRecorder
({
Key
key
,
this
.
child
,
this
.
mode
:
EventRecorderMode
.
stop
,
this
.
onEventsReady
});
final
Widget
child
;
final
EventRecorderMode
mode
;
final
EventsReady
onEventsReady
;
_EventRecorderState
createState
()
=>
new
_EventRecorderState
();
}
class
_EventRecorderState
extends
State
<
EventRecorder
>
{
EventRecorderMode
_mode
;
List
<
PointerInputEvent
>
_events
=
new
List
<
PointerInputEvent
>();
void
initState
()
{
super
.
initState
();
_mode
=
config
.
mode
;
}
void
didUpdateConfig
(
EventRecorder
oldConfig
)
{
if
(
_mode
==
EventRecorderMode
.
record
&&
config
.
mode
==
EventRecorderMode
.
stop
)
{
config
.
onEventsReady
(
_events
);
_events
.
clear
();
}
_mode
=
config
.
mode
;
}
void
_recordEvent
(
PointerInputEvent
event
)
{
if
(
_mode
==
EventRecorderMode
.
record
)
{
_events
.
add
(
event
);
}
}
Widget
build
(
BuildContext
context
)
{
return
new
Listener
(
onPointerDown:
_recordEvent
,
onPointerMove:
_recordEvent
,
onPointerUp:
_recordEvent
,
onPointerCancel:
_recordEvent
,
child:
config
.
child
);
}
}
packages/flutter/lib/widgets.dart
View file @
24ea0f0d
...
@@ -12,6 +12,7 @@ export 'src/widgets/dismissable.dart';
...
@@ -12,6 +12,7 @@ export 'src/widgets/dismissable.dart';
export
'src/widgets/drag_target.dart'
;
export
'src/widgets/drag_target.dart'
;
export
'src/widgets/editable_text.dart'
;
export
'src/widgets/editable_text.dart'
;
export
'src/widgets/enter_exit_transition.dart'
;
export
'src/widgets/enter_exit_transition.dart'
;
export
'src/widgets/event_recorder.dart'
;
export
'src/widgets/focus.dart'
;
export
'src/widgets/focus.dart'
;
export
'src/widgets/framework.dart'
;
export
'src/widgets/framework.dart'
;
export
'src/widgets/gesture_detector.dart'
;
export
'src/widgets/gesture_detector.dart'
;
...
...
packages/unit/benchmark/README.md
0 → 100644
View file @
24ea0f0d
Benchmarks
==========
This directory (and its sub-directories) contain benchmarks for Flutter.
The reporting format for benchmarks is not standardized yet, so benchmarks
here are typically run by hand. To run a particular benchmark, use a command
similar to that used to run individual unit tests. For example:
```
sky/tools/run_tests --debug -r expanded benchmark/gestures/velocity_tracker_bench.dart
```
(The
`-r expanded`
flag prints one line per test, which can be more helpful
than the default format when running individual tests.)
packages/unit/benchmark/gestures/velocity_tracker_bench.dart
0 → 100644
View file @
24ea0f0d
import
'dart:ui'
as
ui
;
import
'package:flutter/gestures.dart'
;
import
'package:test/test.dart'
;
import
'velocity_tracker_data.dart'
;
const
int
kNumIters
=
10000
;
const
int
kBatchSize
=
1000
;
const
int
kBatchOffset
=
50
;
const
int
kNumMarks
=
130
;
List
<
PointerInputEvent
>
_eventFromMap
(
List
<
Map
>
intermediate
)
{
List
<
PointerInputEvent
>
events
=
new
List
<
PointerInputEvent
>();
for
(
Map
entry
in
intermediate
)
events
.
add
(
_eventFor
(
entry
));
return
events
;
}
PointerInputEvent
_eventFor
(
Map
entry
)
{
PointerInputEvent
result
=
new
PointerInputEvent
(
type:
entry
[
'type'
],
timeStamp:
entry
[
'timeStamp'
],
pointer:
entry
[
'pointer'
],
x:
entry
[
'x'
],
y:
entry
[
'y'
]
);
return
result
;
}
void
main
(
)
{
List
<
PointerInputEvent
>
events
=
_eventFromMap
(
velocityEventData
);
test
(
'Dart velocity tracker performance'
,
()
{
VelocityTracker
tracker
=
new
VelocityTracker
();
Stopwatch
watch
=
new
Stopwatch
();
watch
.
start
();
for
(
int
i
=
0
;
i
<
kNumIters
;
i
++)
{
for
(
PointerInputEvent
event
in
events
)
{
if
(
event
.
type
==
'pointerdown'
||
event
.
type
==
'pointermove'
)
tracker
.
addPosition
(
event
.
timeStamp
,
event
.
x
,
event
.
y
);
if
(
event
.
type
==
'pointerup'
)
tracker
.
getVelocity
();
}
}
watch
.
stop
();
print
(
"Dart tracker: "
+
watch
.
elapsed
.
toString
());
});
test
(
'Native velocity tracker performance'
,
()
{
ui
.
VelocityTracker
tracker
=
new
ui
.
VelocityTracker
();
Stopwatch
watch
=
new
Stopwatch
();
watch
.
start
();
for
(
int
i
=
0
;
i
<
kNumIters
;
i
++)
{
for
(
PointerInputEvent
event
in
events
)
{
if
(
event
.
type
==
'pointerdown'
||
event
.
type
==
'pointermove'
)
tracker
.
addPosition
((
event
.
timeStamp
*
1000.0
).
toInt
(),
event
.
x
,
event
.
y
);
if
(
event
.
type
==
'pointerup'
)
tracker
.
getVelocity
();
}
}
watch
.
stop
();
print
(
"Native tracker: "
+
watch
.
elapsed
.
toString
());
});
}
packages/unit/benchmark/gestures/velocity_tracker_data.dart
0 → 100644
View file @
24ea0f0d
This diff is collapsed.
Click to expand it.
packages/unit/test/gestures/lsq_solver_test.dart
0 → 100644
View file @
24ea0f0d
import
'package:flutter/gestures.dart'
;
import
'package:test/test.dart'
;
void
main
(
)
{
approx
(
double
value
,
double
expectation
)
{
const
double
eps
=
1
e
-
6
;
return
(
value
-
expectation
).
abs
()
<
eps
;
}
test
(
'Least-squares fit: linear polynomial to line'
,
()
{
List
<
double
>
x
=
[
0.0
,
1.0
,
2.0
,
3.0
,
4.0
,
5.0
,
6.0
,
7.0
,
8.0
];
List
<
double
>
y
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
];
List
<
double
>
w
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
];
LeastSquaresSolver
solver
=
new
LeastSquaresSolver
(
x
,
y
,
w
);
PolynomialFit
fit
=
solver
.
solve
(
1
);
expect
(
fit
.
coefficients
.
length
,
2
);
expect
(
approx
(
fit
.
coefficients
[
0
],
1.0
),
isTrue
);
expect
(
approx
(
fit
.
coefficients
[
1
],
0.0
),
isTrue
);
expect
(
approx
(
fit
.
confidence
,
1.0
),
isTrue
);
});
test
(
'Least-squares fit: linear polynomial to sloped line'
,
()
{
List
<
double
>
x
=
[
0.0
,
1.0
,
2.0
,
3.0
,
4.0
,
5.0
,
6.0
,
7.0
,
8.0
];
List
<
double
>
y
=
[
1.0
,
2.0
,
3.0
,
4.0
,
5.0
,
6.0
,
7.0
,
8.0
,
9.0
];
List
<
double
>
w
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
];
LeastSquaresSolver
solver
=
new
LeastSquaresSolver
(
x
,
y
,
w
);
PolynomialFit
fit
=
solver
.
solve
(
1
);
expect
(
fit
.
coefficients
.
length
,
2
);
expect
(
approx
(
fit
.
coefficients
[
0
],
1.0
),
isTrue
);
expect
(
approx
(
fit
.
coefficients
[
1
],
1.0
),
isTrue
);
expect
(
approx
(
fit
.
confidence
,
1.0
),
isTrue
);
});
test
(
'Least-squares fit: quadratic polynomial to line'
,
()
{
List
<
double
>
x
=
[
0.0
,
1.0
,
2.0
,
3.0
,
4.0
,
5.0
,
6.0
,
7.0
,
8.0
];
List
<
double
>
y
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
];
List
<
double
>
w
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
];
LeastSquaresSolver
solver
=
new
LeastSquaresSolver
(
x
,
y
,
w
);
PolynomialFit
fit
=
solver
.
solve
(
2
);
expect
(
fit
.
coefficients
.
length
,
3
);
expect
(
approx
(
fit
.
coefficients
[
0
],
1.0
),
isTrue
);
expect
(
approx
(
fit
.
coefficients
[
1
],
0.0
),
isTrue
);
expect
(
approx
(
fit
.
coefficients
[
2
],
0.0
),
isTrue
);
expect
(
approx
(
fit
.
confidence
,
1.0
),
isTrue
);
});
test
(
'Least-squares fit: quadratic polynomial to sloped line'
,
()
{
List
<
double
>
x
=
[
0.0
,
1.0
,
2.0
,
3.0
,
4.0
,
5.0
,
6.0
,
7.0
,
8.0
];
List
<
double
>
y
=
[
1.0
,
2.0
,
3.0
,
4.0
,
5.0
,
6.0
,
7.0
,
8.0
,
9.0
];
List
<
double
>
w
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
,
1.0
];
LeastSquaresSolver
solver
=
new
LeastSquaresSolver
(
x
,
y
,
w
);
PolynomialFit
fit
=
solver
.
solve
(
2
);
expect
(
fit
.
coefficients
.
length
,
3
);
expect
(
approx
(
fit
.
coefficients
[
0
],
1.0
),
isTrue
);
expect
(
approx
(
fit
.
coefficients
[
1
],
1.0
),
isTrue
);
expect
(
approx
(
fit
.
coefficients
[
2
],
0.0
),
isTrue
);
expect
(
approx
(
fit
.
confidence
,
1.0
),
isTrue
);
});
}
packages/unit/test/gestures/velocity_tracker_data.dart
0 → 100644
View file @
24ea0f0d
This diff is collapsed.
Click to expand it.
packages/unit/test/gestures/velocity_tracker_test.dart
0 → 100644
View file @
24ea0f0d
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment