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.
Without this, developers have to override `onReportTimings` to listen for `FrameTiming`.
That can potentially break previous `onReportTimings` listeners if they forget to call
the old listener in their new callback.
This PR replaces the similar RP in the framework: https://github.com/flutter/flutter/pull/38574
Once this PR landed, we'll have to create another framework PR to use the stream to replace
`onReportTimings` usages.
Once that's done, we can then propose the breaking change of removing the deprecated
`onReportTimings`.
Add new optional named oldLayer arguments to all push* methods of the SceneBuilder class.
When not null oldLayer signals to the engine that the intent is to update a layer rendered in a previous frame. The engine may optionally use that signal to reuse the resources allocated for that layer in the previous frame. For example, on the Web we can reuse existing DOM nodes and some of their properties and move fewer nodes around the tree.
The return type of each push method has been tightened up. Instead of having all methods return the same EngineLayer type, each method has its own unique layer type, e.g. OffsetEngineLayer. oldLayer parameters match the returned type. This prevents the framework (and other developers using dart:ui directly) from accidentally supplying an engine layer of the wrong type.