Check if a double is NaN before converting to it int (#61940)
This commit is contained in:
parent
056e455e94
commit
64173f75c3
@ -127,6 +127,13 @@ class MatrixUtils {
|
||||
///
|
||||
/// This function assumes the given point has a z-coordinate of 0.0. The
|
||||
/// z-coordinate of the result is ignored.
|
||||
///
|
||||
/// While not common, this method may return (NaN, NaN), iff the given `point`
|
||||
/// results in a "point at infinity" in homogeneous coordinates after applying
|
||||
/// the `transform`. For example, a [RenderObject] may set its transform to
|
||||
/// the zero matrix to indicate its content is currently not visible. Trying
|
||||
/// to convert an `Offset` to its coordinate space always results in
|
||||
/// (NaN, NaN).
|
||||
static Offset transformPoint(Matrix4 transform, Offset point) {
|
||||
final Float64List storage = transform.storage;
|
||||
final double x = point.dx;
|
||||
|
@ -2293,7 +2293,9 @@ abstract class RenderBox extends RenderObject {
|
||||
/// coordinate system of `ancestor` (which must be an ancestor of this render
|
||||
/// object) instead of to the global coordinate system.
|
||||
///
|
||||
/// This method is implemented in terms of [getTransformTo].
|
||||
/// This method is implemented in terms of [getTransformTo]. If the transform
|
||||
/// matrix puts the given `point` on the line at infinity (for instance, when
|
||||
/// the transform matrix is the zero matrix), this method returns (NaN, NaN).
|
||||
Offset localToGlobal(Offset point, { RenderObject ancestor }) {
|
||||
return MatrixUtils.transformPoint(getTransformTo(ancestor), point);
|
||||
}
|
||||
|
@ -1936,10 +1936,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
||||
Offset _getPixelPerfectCursorOffset(Rect caretRect) {
|
||||
final Offset caretPosition = localToGlobal(caretRect.topLeft);
|
||||
final double pixelMultiple = 1.0 / _devicePixelRatio;
|
||||
final int quotientX = (caretPosition.dx / pixelMultiple).round();
|
||||
final int quotientY = (caretPosition.dy / pixelMultiple).round();
|
||||
final double pixelPerfectOffsetX = quotientX * pixelMultiple - caretPosition.dx;
|
||||
final double pixelPerfectOffsetY = quotientY * pixelMultiple - caretPosition.dy;
|
||||
final double pixelPerfectOffsetX = caretPosition.dx.isFinite
|
||||
? (caretPosition.dx / pixelMultiple).round() * pixelMultiple - caretPosition.dx
|
||||
: caretPosition.dx;
|
||||
final double pixelPerfectOffsetY = caretPosition.dy.isFinite
|
||||
? (caretPosition.dy / pixelMultiple).round() * pixelMultiple - caretPosition.dy
|
||||
: caretPosition.dy;
|
||||
return Offset(pixelPerfectOffsetX, pixelPerfectOffsetY);
|
||||
}
|
||||
|
||||
|
@ -4321,6 +4321,30 @@ void main() {
|
||||
expect(scrollController.offset, 0);
|
||||
});
|
||||
|
||||
testWidgets('getLocalRectForCaret does not throw when it sees an infinite point', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: SkipPainting(
|
||||
child: Transform(
|
||||
transform: Matrix4.zero(),
|
||||
child: EditableText(
|
||||
controller: TextEditingController(),
|
||||
focusNode: FocusNode(),
|
||||
style: textStyle,
|
||||
cursorColor: Colors.blue,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final EditableTextState state = tester.state<EditableTextState>(find.byType(EditableText));
|
||||
final Rect rect = state.renderEditable.getLocalRectForCaret(const TextPosition(offset: 0));
|
||||
expect(rect.isFinite, false);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('obscured multiline fields throw an exception', (WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController();
|
||||
expect(
|
||||
@ -5350,3 +5374,15 @@ class NoImplicitScrollPhysics extends AlwaysScrollableScrollPhysics {
|
||||
return NoImplicitScrollPhysics(parent: buildParent(ancestor));
|
||||
}
|
||||
}
|
||||
|
||||
class SkipPainting extends SingleChildRenderObjectWidget {
|
||||
const SkipPainting({ Key key, Widget child }): super(key: key, child: child);
|
||||
|
||||
@override
|
||||
SkipPaintingRenderObject createRenderObject(BuildContext context) => SkipPaintingRenderObject();
|
||||
}
|
||||
|
||||
class SkipPaintingRenderObject extends RenderProxyBox {
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) { }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user