mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
<!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> ### Problem The P3-to-sRGB color conversion applies an affine matrix directly to gamma-encoded values in both the C++ engine (`dl_color.cc`) and Dart (`painting.dart`). This is mathematically incorrect — color space conversion matrices must operate in linear light. The result is P3 colors that appear nearly identical to sRGB instead of showing the full gamut difference. For example, P3 `#1ECAD3` (30/255, 202/255, 211/255) converts to: - **Old (wrong):** extendedSRGB (-0.12, 0.86, 0.87) - **New (correct):** extendedSRGB (-0.38, 0.81, 0.84) The red channel error of 0.26 is clearly visible — colors appear washed out instead of vivid. ### Fix Replace the single affine matrix multiply with the correct 3-step pipeline: 1. **Linearize** — decode gamma via sRGB EOTF 2. **Transform** — apply 3x3 P3-to-sRGB matrix in linear space 3. **Encode** — re-apply gamma via sRGB OETF Extended range (negative values from out-of-gamut colors) is handled by mirroring the transfer function. **C++ (`dl_color.cc`):** Replace affine matrix with `p3ToExtendedSrgb()` using `double` precision. **Dart (`painting.dart`):** Replace `_MatrixColorTransform` with `_P3ToSrgbTransform` and `_SrgbToP3Transform` classes. Also fixes the sRGB-to-P3 direction. ### Performance Negligible. The C++ conversion runs once per paint setup in `ReadColor`, not per frame or per pixel. The Dart conversion runs once per `Color.withValues()` call. ### Tests - **C++:** Added `ColorSpaceP3ToExtendedSRGBLinearLight` test in `dl_color_unittests.cc` - **Dart:** Added 3 tests in `colors_test.dart`: mid-range P3→extendedSRGB, P3 green→extendedSRGB, sRGB→P3 round-trip All new tests fail with the old code and pass with the fix. Existing tests continue to pass. ## Issue: https://github.com/flutter/flutter/issues/181717 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. **New tests pass, can't run golden tests!** --------- Co-authored-by: gaaclarke <30870216+gaaclarke@users.noreply.github.com>