This updates the web_ui implementation of lerpDouble to match the
behaviour of the C++ engine implementation in dart:ui.
Specifically this covers the following changes:
* #20871: stricter handling of NaN and infinity
* #20879: Improve the precision of lerpDouble
lerpDouble: stricter handling of NaN and infinity (#20871)
----------------------------------------------------------
Previously, the behaviour of lerpDouble with respect to NaN and infinity
was relatively complex and difficult to reason about. This patch
simplifies the behaviour with respect to those conditions and adds
documentation and tests.
In general, if `a == b` or both values are null, infinite, or NaN, `a`
is returned. Otherwise we require `a` and `b` and `t` to be finite or
null and the result of the linear interpolation is returned.
Improve the precision of lerpDouble (#20879)
--------------------------------------------
Reduces errors caused by the loss of floating point precision when the
two extrema of the lerp differ significantly in magnitude. Previously,
we used the calculation:
a + (b - a) * t
When the difference in magnitude between `a` and `b` exceeds the
precision representable by double-precision floating point math, `b - a`
results in the larger-magnitude value of `a` or `b`. The error between
the value produced and the correct value is then scaled by t.
A simple example of the impact can be seen when `a` is significantly
larger in magnitude than `b`. In that case, `b - a` results in `a` and
when `t` is 1.0, the resulting value is `a - (a) * 1.0 == 0`.
The patch transforms the computation to the mathematically-equivalent
expression:
a * (1.0 - t) + b * t
By scaling each value independently, the behaviour is more accurate.
From the point of view of performance, this adds an extra
multiplication, but multiplication is relatively cheap and the behaviour
is significantly better.
This patch also adds a `precisionErrorTolerance` constant to
test_utils.dart and migrates existing tests to use `closeTo()` for
testing.
The tests themselves *do* currently use values that have an exact
floating-point representation, but we should allow for flexibility in
future implementation changes.
Reduces errors caused by the loss of floating point precision when the
two extrema of the lerp differ significantly in magnitude. Previously,
we used the calculation:
a + (b - a) * t
When the difference in magnitude between `a` and `b` exceeds the
precision representable by double-precision floating point math, `b - a`
results in the larger-magnitude value of `a` or `b`. The error between
the value produced and the correct value is then scaled by t.
A simple example of the impact can be seen when `a` is significantly
larger in magnitude than `b`. In that case, `b - a` results in `a` and
when `t` is 1.0, the resulting value is `a - (a) * 1.0 == 0`.
The patch transforms the computation to the mathematically-equivalent
expression:
a * (1.0 - t) + b * t
By scaling each value independently, the behaviour is more accurate.
From the point of view of performance, this adds an extra
multiplication, but multiplication is relatively cheap and the behaviour
is significantly better.
This patch also adds a `precisionErrorTolerance` constant to
test_utils.dart and migrates existing tests to use `closeTo()` for
testing.
The tests themselves *do* currently use values that have an exact
floating-point representation, but we should allow for flexibility in
future implementation changes.
Previously, the behaviour of lerpDouble with respect to NaN and infinity
was relatively complex and difficult to reason about. This patch
simplifies the behaviour with respect to those conditions and adds
documentation and tests.
In general, if `a == b` or both values are null, infinite, or NaN, `a`
is returned. Otherwise we require `a` and `b` and `t` to be finite or
null and the result of the linear interpolation is returned.
This extracts a Dart test utilities library, containing
`expectAssertion` and `expectArgumentError` functions that simplify
running tests that test assertions across debug, profile, and release
configurations.
This change also restricts Dart unit tests to testing files whose
filename matches `*_test.dart` under `flutter/testing/dart`; previously
any file in that directory was run, but all files matched the above
pattern.
The behaviour of lerpDouble with respect to null inputs isn't entirely
obvious. In the case where both inputs are null, it returns null.
Otherwise, it defaults the null parameter to 0.0 and carries on.
Post non-null by default, it might be nice to strengthen the parameter
contract to require them to be non-null. While this would be a breaking
change, it seems likely that the framework either meets this guarantee
or can provide it without a framework breaking change.
https://github.com/flutter/flutter/issues/64617 tracks the above.
In the meantime, adding a test to lock in the current behaviour.
Reland #19396 with a fix for improper scale that was affecting internal tests
Tested: Ran all unittests, ran internal tests, and ran workstation on Fuchsia
BUG: 53062, 53063
The fuchsia code around metrics and sizing was just sending this
information through a side-channel, when the engine already had the
information available. So, delete all of it to make future CLs simpler.
Additionally, the SceneUpdateContext has many unneccesary dependencies
re: metrics and PaintTasks. Break those to make future CLs simpler.
Tested: Ran all unittests and ran workstation on Fuchsia
BUG: 53062, 53063
* Manual merge or Dart into flutter a3815b6590...24c7666def
dart-lang/sdk@24c7666def Update tests that have the current version number hardcoded
dart-lang/sdk@f88ce7aef5 Increase Dart version to 2.10
* Update language version.
* Update license.
* Hpdate language version.
* Update license.
Refactors instantiateImageCodec and decodeImageFromPixels to provide intermediate data about the image width, height, and bytes per pixel. This allows for more fine grained control from Dart, particularly when trying to reason about how or whether to maintain aspect ratio in the targetWidth/targetHeight parameters.
This leaves the existing methods functional by re-implementing them to use the new ImmutableBuffer/ImageDescriptor class.
The ImmutableBuffer class is provided so that callers can avoid copying the image data multiple times if they wish to re-recreate the image descriptor.
Related Issues
Adds an `allowUpscale` parameter to the Dart interfaces for instantiateImageCodec and decodeImageFromPIxels. If set to false, the image bounds will be clamped at their intrinsic dimensions.
A later commit will change the default to true.
SkImage references get held by both our Image and Picture objects. The GC has no idea about this, and so sometimes pictures look very small when they're actually holding a reference to a large chunk of memory. This patch helps make sure that the GC can more adequately catch the real size impact of Picture objects, and combined with an upstream patch in Dart allows for much more aggressive collection of unused image related memory.
* "Reland Clang 11, roll buildroot to 1bc40a5f916adb93d87e2a2230a0ec43db876c1c, take 4 (#17467)" (#17482)"
This reverts commit 8166a91bca11b83c16fba8f8fd407e937a2ac89c.
* format code
* Roll buildroot to 3a27de1c5bb0f50be7d3efe3e00de4f6068c9f30
* Reland Clang 11, Roll buildroot to 1bc40a5f916adb93d87e2a2230a0ec43db876c1c (#17457)" (#17464)
This reverts commit 9eacd028cdba5c6efef327342dc53fab61474462.
* Skip more image tests, use newer dsymutil, add missing symbols
Constructing colors using `fromRGBO` should return the same values as the CSS
`rgba()` notation. rgba(0, 0, 255, 0.5) is the same as `#0000ff80`
However `fromRGBO` sometimes creates a color with an off-by-one alpha value:
expect(Color.fromRGBO(0, 0, 255, 0.5), Color(0x800000ff));
Expected: Color:<Color(0x800000ff)>
Actual: Color:<Color(0x7f0000ff)>
If we use `withOpacity` to create the same color, it returns the correct color:
expect(Color.fromRGBO(0, 0, 255, 1).withOpacity(0.5), Color(0x800000ff));
This should also be changed in lib/web_ui/lib/src/ui/painting.dart in a
followup change.
Make ImageFilter objects comparable and printable.
This will help in areas in the Widget and RenderObject trees which try to avoid marking objects for updates if a setter is called with the same value (previously all ImageFilter objects would compare as not equal and appear to be new values).
This removes TextRange from the framework and moves it to the engine, in preparation for using it to return text ranges from the text extent APIs, like Paragraph.getWordBoundary instead of a List<int>.
Also added new tests for TextRange.