From 227e44d9e580945e4ef3e25d2e73ebb31e01f41a Mon Sep 17 00:00:00 2001 From: Ferhat Date: Tue, 22 Oct 2019 16:46:38 -0700 Subject: [PATCH] [web] Cupertino dynamic color fix. (#13296) * Fix cupertino theme rendering issues due to Color subclassing Fixes flutter/flutter#41257 --- lib/web_ui/lib/src/ui/painting.dart | 48 ++++++++++++++++------------- lib/web_ui/test/color_test.dart | 17 ++++++++++ 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/lib/web_ui/lib/src/ui/painting.dart b/lib/web_ui/lib/src/ui/painting.dart index 74bb88387eb..ed1a4a392f4 100644 --- a/lib/web_ui/lib/src/ui/painting.dart +++ b/lib/web_ui/lib/src/ui/painting.dart @@ -43,11 +43,11 @@ class Color { /// Bits 16-23 are the red value. /// Bits 8-15 are the green value. /// Bits 0-7 are the blue value. - const Color(int value) : _value = value & 0xFFFFFFFF; + const Color(int value) : this.value = value & 0xFFFFFFFF; /// Construct a color from the lower 8 bits of four integers. const Color.fromARGB(int a, int r, int g, int b) - : _value = (((a & 0xff) << 24) | + : value = (((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff) << 0)) & @@ -65,7 +65,7 @@ class Color { /// /// See also [fromARGB], which takes the opacity as an integer value. const Color.fromRGBO(int r, int g, int b, double opacity) - : _value = ((((opacity * 0xff ~/ 1) & 0xff) << 24) | + : value = ((((opacity * 0xff ~/ 1) & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff) << 0)) & @@ -77,23 +77,22 @@ class Color { /// Bits 16-23 are the red value. /// Bits 8-15 are the green value. /// Bits 0-7 are the blue value. - int get value => _value; - final int _value; + final int value; /// The alpha channel of this color in an 8 bit value. - int get alpha => (0xff000000 & _value) >> 24; + int get alpha => (0xff000000 & value) >> 24; /// The alpha channel of this color as a double. double get opacity => alpha / 0xFF; /// The red channel of this color in an 8 bit value. - int get red => (0x00ff0000 & _value) >> 16; + int get red => (0x00ff0000 & value) >> 16; /// The green channel of this color in an 8 bit value. - int get green => (0x0000ff00 & _value) >> 8; + int get green => (0x0000ff00 & value) >> 8; /// The blue channel of this color in an 8 bit value. - int get blue => (0x000000ff & _value) >> 0; + int get blue => (0x000000ff & value) >> 0; /// Returns a new color that matches this color with the alpha channel /// replaced with a (which ranges from 0 to 255). @@ -240,22 +239,22 @@ class Color { } @override - int get hashCode => _value.hashCode; + int get hashCode => value.hashCode; /// Converts color to a css compatible attribute value. // webOnly String toCssString() { - if ((0xff000000 & _value) == 0xff000000) { + if ((0xff000000 & value) == 0xff000000) { return toCssStringRgbOnly(); } else { - final double alpha = ((_value >> 24) & 0xFF) / 255.0; + final double alpha = ((value >> 24) & 0xFF) / 255.0; final StringBuffer sb = StringBuffer(); sb.write('rgba('); - sb.write(((_value >> 16) & 0xFF).toString()); + sb.write(((value >> 16) & 0xFF).toString()); sb.write(','); - sb.write(((_value >> 8) & 0xFF).toString()); + sb.write(((value >> 8) & 0xFF).toString()); sb.write(','); - sb.write((_value & 0xFF).toString()); + sb.write((value & 0xFF).toString()); sb.write(','); sb.write(alpha.toString()); sb.write(')'); @@ -269,7 +268,7 @@ class Color { /// with the paint opacity. // webOnly String toCssStringRgbOnly() { - final String paddedValue = '00000${_value.toRadixString(16)}'; + final String paddedValue = '00000${value.toRadixString(16)}'; return '#${paddedValue.substring(paddedValue.length - 6)}'; } @@ -1396,7 +1395,8 @@ abstract class ColorFilter { /// The output of this filter is then composited into the background according /// to the [Paint.blendMode], using the output of this filter as the source /// and the background as the destination. - const factory ColorFilter.mode(Color color, BlendMode blendMode) = engine.EngineColorFilter.mode; + const factory ColorFilter.mode(Color color, BlendMode blendMode) = + engine.EngineColorFilter.mode; /// Construct a color filter that transforms a color by a 4x5 matrix. /// @@ -1456,22 +1456,25 @@ abstract class ColorFilter { /// 0, 0, 0, 1, 0, /// ]); /// ``` - const factory ColorFilter.matrix(List matrix) = engine.EngineColorFilter.matrix; + const factory ColorFilter.matrix(List matrix) = + engine.EngineColorFilter.matrix; /// Construct a color filter that applies the sRGB gamma curve to the RGB /// channels. - const factory ColorFilter.linearToSrgbGamma() = engine.EngineColorFilter.linearToSrgbGamma; + const factory ColorFilter.linearToSrgbGamma() = + engine.EngineColorFilter.linearToSrgbGamma; /// Creates a color filter that applies the inverse of the sRGB gamma curve /// to the RGB channels. - const factory ColorFilter.srgbToLinearGamma() = engine.EngineColorFilter.srgbToLinearGamma; + const factory ColorFilter.srgbToLinearGamma() = + engine.EngineColorFilter.srgbToLinearGamma; List webOnlySerializeToCssPaint() { throw UnsupportedError('ColorFilter for CSS paint not yet supported'); } @override - bool operator==(dynamic other); + bool operator ==(dynamic other); @override int get hashCode; @@ -1743,7 +1746,8 @@ class Codec { /// /// The returned future can complete with an error if the image decoding has /// failed. -Future instantiateImageCodec(Uint8List list, { +Future instantiateImageCodec( + Uint8List list, { int targetWidth, int targetHeight, }) { diff --git a/lib/web_ui/test/color_test.dart b/lib/web_ui/test/color_test.dart index 93f309fa735..863fa4f42fa 100644 --- a/lib/web_ui/test/color_test.dart +++ b/lib/web_ui/test/color_test.dart @@ -137,4 +137,21 @@ void main() { // 0.0722 * ((0.18823529411 + 0.055) / 1.055) ^ 2.4 expect(brightRed.computeLuminance(), equals(0.24601329637099723)); }); + + // Regression test for https://github.com/flutter/flutter/issues/41257 + // CupertinoDynamicColor was overriding base class and calling super(0). + test('subclass of Color can override value', () { + final DynamicColorClass color = DynamicColorClass(0xF0E0D0C0); + expect(color.value, 0xF0E0D0C0); + // Call base class member, make sure it uses overridden value. + expect(color.red, 0xE0); + }); +} + +class DynamicColorClass extends Color { + const DynamicColorClass(int newValue) : _newValue = newValue, super(0); + + final int _newValue; + + int get value => _newValue; }