Skip to content

Commit 687cf08

Browse files
author
Jonah Williams
authored
Add option to invert paint colors to be used for smart invert accessibility on iOS (flutter#6176)
1 parent 85d47fb commit 687cf08

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

lib/ui/painting.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ class Paint {
10651065
static const int _kMaskFilterIndex = 12;
10661066
static const int _kMaskFilterBlurStyleIndex = 13;
10671067
static const int _kMaskFilterSigmaIndex = 14;
1068+
static const int _kInvertColorIndex = 15;
10681069

10691070
static const int _kIsAntiAliasOffset = _kIsAntiAliasIndex << 2;
10701071
static const int _kColorOffset = _kColorIndex << 2;
@@ -1081,6 +1082,7 @@ class Paint {
10811082
static const int _kMaskFilterOffset = _kMaskFilterIndex << 2;
10821083
static const int _kMaskFilterBlurStyleOffset = _kMaskFilterBlurStyleIndex << 2;
10831084
static const int _kMaskFilterSigmaOffset = _kMaskFilterSigmaIndex << 2;
1085+
static const int _kInvertColorOffset = _kInvertColorIndex << 2;
10841086
// If you add more fields, remember to update _kDataByteCount.
10851087
static const int _kDataByteCount = 75;
10861088

@@ -1363,6 +1365,18 @@ class Paint {
13631365
}
13641366
}
13651367

1368+
/// Whether the colors of the image are inverted when drawn.
1369+
///
1370+
/// inverting the colors of an image applies a new color filter that will
1371+
/// be composed with any user provided color filters. This is primarily
1372+
/// used for implementing smart invert on iOS.
1373+
bool get invertColors {
1374+
return _data.getInt32(_kInvertColorOffset, _kFakeHostEndian) == 1;
1375+
}
1376+
set invertColors(bool value) {
1377+
_data.setInt32(_kInvertColorOffset, value ? 1 : 0, _kFakeHostEndian);
1378+
}
1379+
13661380
@override
13671381
String toString() {
13681382
final StringBuffer result = new StringBuffer();
@@ -1411,8 +1425,12 @@ class Paint {
14111425
result.write('${semicolon}filterQuality: $filterQuality');
14121426
semicolon = '; ';
14131427
}
1414-
if (shader != null)
1428+
if (shader != null) {
14151429
result.write('${semicolon}shader: $shader');
1430+
semicolon = '; ';
1431+
}
1432+
if (invertColors)
1433+
result.write('${semicolon}invert: $invertColors');
14161434
result.write(')');
14171435
return result.toString();
14181436
}

lib/ui/painting/paint.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ constexpr int kColorFilterBlendModeIndex = 11;
3030
constexpr int kMaskFilterIndex = 12;
3131
constexpr int kMaskFilterBlurStyleIndex = 13;
3232
constexpr int kMaskFilterSigmaIndex = 14;
33+
constexpr int kInvertColorIndex = 15;
3334
constexpr size_t kDataByteCount = 75; // 4 * (last index + 1)
3435

3536
// Indices for objects.
@@ -47,6 +48,16 @@ constexpr uint32_t kBlendModeDefault =
4748
// default SkPaintDefaults_MiterLimit in Skia (which is not in a public header).
4849
constexpr double kStrokeMiterLimitDefault = 4.0;
4950

51+
// A color matrix which inverts colors.
52+
// clang-format off
53+
constexpr SkScalar invert_colors[20] = {
54+
-1.0, 0, 0, 1.0, 0,
55+
0, -1.0, 0, 1.0, 0,
56+
0, 0, -1.0, 1.0, 0,
57+
1.0, 1.0, 1.0, 1.0, 0
58+
};
59+
// clang-format on
60+
5061
// Must be kept in sync with the MaskFilter private constants in painting.dart.
5162
enum MaskFilterType { Null, Blur };
5263

@@ -116,7 +127,19 @@ Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) {
116127
if (filter_quality)
117128
paint_.setFilterQuality(static_cast<SkFilterQuality>(filter_quality));
118129

119-
if (uint_data[kColorFilterIndex]) {
130+
if (uint_data[kColorFilterIndex] && uint_data[kInvertColorIndex]) {
131+
SkColor color = uint_data[kColorFilterColorIndex];
132+
SkBlendMode blend_mode =
133+
static_cast<SkBlendMode>(uint_data[kColorFilterBlendModeIndex]);
134+
sk_sp<SkColorFilter> color_filter =
135+
SkColorFilter::MakeModeFilter(color, blend_mode);
136+
sk_sp<SkColorFilter> invert_filter =
137+
SkColorFilter::MakeMatrixFilterRowMajor255(invert_colors);
138+
paint_.setColorFilter(invert_filter->makeComposed(color_filter));
139+
} else if (uint_data[kInvertColorIndex]) {
140+
paint_.setColorFilter(
141+
SkColorFilter::MakeMatrixFilterRowMajor255(invert_colors));
142+
} else if (uint_data[kColorFilterIndex]) {
120143
SkColor color = uint_data[kColorFilterColorIndex];
121144
SkBlendMode blend_mode =
122145
static_cast<SkBlendMode>(uint_data[kColorFilterBlendModeIndex]);

0 commit comments

Comments
 (0)