Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds wide gamut framework breakage notice. #11082

Merged
merged 12 commits into from
Sep 6, 2024
135 changes: 135 additions & 0 deletions src/release/breaking-changes/wide-gamut-framework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: Migration guide for wide gamut Color
description: Description on Color changes for wide gamut support and migration
instructions.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
---

## Summary

The API for the [`Color`][] class in `dart:ui` is changing to support wide gamut
colors.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

## Context
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

The Flutter engine [already supports wide gamut color][] with [Impeller][], and the support is now being added [to the framework][].

The iOS devices Flutter targets support rendering a larger array of colors,
specifically the [DisplayP3][] color space. After this change, the Flutter
framework will be able to render all of those colors on iOS Impeller and `Color`
will be better prepared for the future addition of color spaces or changes to
color component bit depth.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

## Description of change

Changes to [`Color`][]:

1. Adds a enum field which will specify its [`ColorSpace`][].
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
1. Adds API to use normalized floating-point color components.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
1. Removes API that uses 8-bit unsigned integer color components that can lead
to data loss.

Changes to [`ColorSpace`][]:

1. `displayP3` will be added.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

## Migration guide

### 8-bit unsigned integer constructors

Constructors like `Color.fromARGB` will remain unchanged and have continued
support. If one wants to take advantage of Display P3 colors they will have to
use the new `Color.from` constructor that takes normalized floating-point
color components.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

```dart
// Before
final magenta = Color.fromARGB(0xff, 0xff, 0x0, 0xff);
// After
final magenta = Color.from(alpha: 1.0, red: 1.0, green: 0.0, blue: 1.0)
```

### Implementors of `Color`
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Implementors of `Color`
### Apps that reimplement `Color`

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implements is a specific Dart concept and keyword. How about "Class that implements Color"?


There are new methods being added to `Color` so any class that `implements`
Color will break and have to implement the new methods like `Color.a`, and
`Color.b`. Ultimately implementors should be migrated to take advantage of the
new API. In the short-term, these methods can easily be implemented without
changing the underlying structure of your class.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
There are new methods being added to `Color` so any class that `implements`
Color will break and have to implement the new methods like `Color.a`, and
`Color.b`. Ultimately implementors should be migrated to take advantage of the
new API. In the short-term, these methods can easily be implemented without
changing the underlying structure of your class.
Because this change adds new methods to `Color`, any app that implements `Color`
will break and must be updated to implement the new methods, like `Color.a` and `Color.b`.
In the short-term, you can do this without changing the underlying structure of your class.
However, in the long term, your reimplementation of `Color` should take advantage of the new API.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think implements should be treated as a specific Dart concept and not talked about generally. It means that you are making a class that guarantees will match another classes public interface.


For example:

```dart
class Foo implements Color {
int _red;

@override
double get r => _red * 255.0;
}
```

{{site.alert.note}}
The hope is to eventually make Color `sealed`. Now might be a good opportunity
to stop implementing `Color`. Instead of inheritance, switch to composition.
{{site.alert.end}}
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

### Color space support

Clients that use `Color` and perform any sort of calculation on the color
components should now be checking the color space component before doing any
such calculation. `Color` has a new method `Color.withValues` that can be used
to perform color space conversions to help with that.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

For example:

```dart
// Before
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
double redRatio(Color x, Color y) => x.red / y.red;

// After
double redRatio(Color x, Color y) {
final xPrime = x.withValues(colorSpace: ColorSpace.extendedSRGB);
final yPrime = y.withValues(colorSpace: ColorSpace.extendedSRGB);
return xPrime.r / yPrime.r;
}
```

### Color component accessors
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

For users of `Color`, if the components are ever accessed the code should be
migrated to take advantage of the floating-point components. In the short term
one can easily scale the components themselves.
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

```dart
extension IntColorComponents on Color {
int get intAlpha => this.a ~/ 255;
int get intRed => this.r ~/ 255;
int get intGreen => this.g ~/ 255;
int get intBlue => this.b ~/ 255;
}
```

## Timeline

### Phase 1 - New API introduction, old API deprecation

**Release to stable:** TBD
**PR:**: [PR 54737][]

### Phase 2 - Old API removal

**Release to stable:** TBD

## References

Relevant PRs:

* [issue 127855][]: Implement wide gamut color support in the Framework

[`Color`]: {{site.api}}/flutter/dart-ui/Color-class.html
[already supports wide gamut color]: {{site.repo.flutter}}/issues/55092
[to the framework]: {{site.repo.flutter}}/issues/127855
[issue 127855]: {{site.repo.flutter}}/issues/127855
[`ColorSpace`]: {{site.api}}/flutter/dart-ui/ColorSpace.html
[PR 54737]: {{site.repo.engine}}/pull/54737
[DisplayP3]: https://en.wikipedia.org/wiki/DCI-P3
[Impeller]: {{site.api}}/perf/impeller