Skip to content

Commit

Permalink
Fix typo in MediaQuery.fromWindow and add invertColors flag to images…
Browse files Browse the repository at this point in the history
… for smart invert. (#21457)
  • Loading branch information
jonahwilliams committed Sep 12, 2018
1 parent 5ea987d commit 23499f4
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 2 deletions.
7 changes: 7 additions & 0 deletions packages/flutter/lib/src/painting/decoration_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,11 @@ class DecorationImagePainter {
/// when using this, to not flip images with integral shadows, text, or other
/// effects that will look incorrect when flipped.
///
/// * `invertColors`: Inverting the colors of an image applies a new color
/// filter to the paint. If there is another specified color filter, the
/// invert will be applied after it. This is primarily used for implementing
/// smart invert on iOS.
///
/// The `canvas`, `rect`, `image`, `scale`, `alignment`, `repeat`, and `flipHorizontally`
/// arguments must not be null.
///
Expand All @@ -361,6 +366,7 @@ void paintImage({
Rect centerSlice,
ImageRepeat repeat = ImageRepeat.noRepeat,
bool flipHorizontally = false,
bool invertColors = false,
}) {
assert(canvas != null);
assert(image != null);
Expand Down Expand Up @@ -406,6 +412,7 @@ void paintImage({
// to nearest-neighbor.
paint.filterQuality = FilterQuality.low;
}
paint.invertColors = invertColors;
final double halfWidthDelta = (outputSize.width - destinationSize.width) / 2.0;
final double halfHeightDelta = (outputSize.height - destinationSize.height) / 2.0;
final double dx = halfWidthDelta + (flipHorizontally ? -alignment.x : alignment.x) * halfWidthDelta;
Expand Down
18 changes: 18 additions & 0 deletions packages/flutter/lib/src/rendering/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class RenderImage extends RenderBox {
Rect centerSlice,
bool matchTextDirection = false,
TextDirection textDirection,
bool invertColors = false
}) : assert(scale != null),
assert(repeat != null),
assert(alignment != null),
Expand All @@ -52,6 +53,7 @@ class RenderImage extends RenderBox {
_repeat = repeat,
_centerSlice = centerSlice,
_matchTextDirection = matchTextDirection,
_invertColors = invertColors,
_textDirection = textDirection {
_updateColorFilter();
}
Expand Down Expand Up @@ -215,6 +217,20 @@ class RenderImage extends RenderBox {
markNeedsPaint();
}

/// Whether to invert the colors of the image.
///
/// inverting the colors of an image applies a new color filter to the paint.
/// If there is another specified color filter, the invert will be applied
/// after it. This is primarily used for implementing smart invert on iOS.
bool get invertColors => _invertColors;
bool _invertColors;
set invertColors(bool value) {
if (value == _invertColors)
return;
_invertColors = value;
markNeedsPaint();
}

/// Whether to paint the image in the direction of the [TextDirection].
///
/// If this is true, then in [TextDirection.ltr] contexts, the image will be
Expand Down Expand Up @@ -331,6 +347,7 @@ class RenderImage extends RenderBox {
centerSlice: _centerSlice,
repeat: _repeat,
flipHorizontally: _flipHorizontally,
invertColors: invertColors,
);
}

Expand All @@ -349,5 +366,6 @@ class RenderImage extends RenderBox {
properties.add(DiagnosticsProperty<Rect>('centerSlice', centerSlice, defaultValue: null));
properties.add(FlagProperty('matchTextDirection', value: matchTextDirection, ifTrue: 'match text direction'));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('invertColors', invertColors));
}
}
17 changes: 16 additions & 1 deletion packages/flutter/lib/src/widgets/basic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4494,6 +4494,7 @@ class RawImage extends LeafRenderObjectWidget {
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.invertColors = false,
}) : assert(scale != null),
assert(alignment != null),
assert(repeat != null),
Expand Down Expand Up @@ -4595,6 +4596,17 @@ class RawImage extends LeafRenderObjectWidget {
/// scope.
final bool matchTextDirection;

/// Whether the colors of the image are inverted when drawn.
///
/// inverting the colors of an image applies a new color filter to the paint.
/// If there is another specified color filter, the invert will be applied
/// after it. This is primarily used for implementing smart invert on iOS.
///
/// See also:
///
/// * [Paint.invertColors], for the dart:ui implementation.
final bool invertColors;

@override
RenderImage createRenderObject(BuildContext context) {
assert((!matchTextDirection && alignment is Alignment) || debugCheckHasDirectionality(context));
Expand All @@ -4611,6 +4623,7 @@ class RawImage extends LeafRenderObjectWidget {
centerSlice: centerSlice,
matchTextDirection: matchTextDirection,
textDirection: matchTextDirection || alignment is! Alignment ? Directionality.of(context) : null,
invertColors: invertColors,
);
}

Expand All @@ -4628,7 +4641,8 @@ class RawImage extends LeafRenderObjectWidget {
..repeat = repeat
..centerSlice = centerSlice
..matchTextDirection = matchTextDirection
..textDirection = matchTextDirection || alignment is! Alignment ? Directionality.of(context) : null;
..textDirection = matchTextDirection || alignment is! Alignment ? Directionality.of(context) : null
..invertColors = invertColors;
}

@override
Expand All @@ -4645,6 +4659,7 @@ class RawImage extends LeafRenderObjectWidget {
properties.add(EnumProperty<ImageRepeat>('repeat', repeat, defaultValue: ImageRepeat.noRepeat));
properties.add(DiagnosticsProperty<Rect>('centerSlice', centerSlice, defaultValue: null));
properties.add(FlagProperty('matchTextDirection', value: matchTextDirection, ifTrue: 'match text direction'));
properties.add(DiagnosticsProperty<bool>('invertColors', invertColors));
}
}

Expand Down
5 changes: 5 additions & 0 deletions packages/flutter/lib/src/widgets/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/services.dart';
import 'package:flutter/semantics.dart';

import 'basic.dart';
import 'framework.dart';
Expand Down Expand Up @@ -550,9 +551,12 @@ class _ImageState extends State<Image> {
ImageStream _imageStream;
ImageInfo _imageInfo;
bool _isListeningToStream = false;
bool _invertColors;

@override
void didChangeDependencies() {
_invertColors = MediaQuery.of(context, nullOk: true)?.invertColors
?? SemanticsBinding.instance.accessibilityFeatures.invertColors;
_resolveImage();

if (TickerMode.of(context))
Expand Down Expand Up @@ -645,6 +649,7 @@ class _ImageState extends State<Image> {
repeat: widget.repeat,
centerSlice: widget.centerSlice,
matchTextDirection: widget.matchTextDirection,
invertColors: _invertColors,
);
if (widget.excludeFromSemantics)
return image;
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/widgets/media_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class MediaQueryData {
padding = EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio),
viewInsets = EdgeInsets.fromWindowPadding(window.viewInsets, window.devicePixelRatio),
accessibleNavigation = window.accessibilityFeatures.accessibleNavigation,
invertColors = window.accessibilityFeatures.accessibleNavigation,
invertColors = window.accessibilityFeatures.invertColors,
disableAnimations = window.accessibilityFeatures.disableAnimations,
boldText = window.accessibilityFeatures.boldText,
alwaysUse24HourFormat = window.alwaysUse24HourFormat;
Expand Down
1 change: 1 addition & 0 deletions packages/flutter/test/rendering/image_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void main() {
' size: Size(25.0, 25.0)\n'
' image: [10×10]\n'
' alignment: center\n'
' invertColors: false\n'
),
);

Expand Down
106 changes: 106 additions & 0 deletions packages/flutter/test/widgets/invert_colors_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
testWidgets('InvertColors', (WidgetTester tester) async {
await tester.pumpWidget(const RepaintBoundary(
child: SizedBox(
width: 200.0,
height: 200.0,
child: InvertColorTestWidget(
color: Color.fromRGBO(255, 0, 0, 1.0),
),
),
));

await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('invert_colors_test.0.png'),
skip: !Platform.isLinux,
);
});

testWidgets('InvertColors and ColorFilter', (WidgetTester tester) async {
await tester.pumpWidget(const RepaintBoundary(
child: SizedBox(
width: 200.0,
height: 200.0,
child: InvertColorTestWidget(
color: Color.fromRGBO(255, 0, 0, 1.0),
filter: ColorFilter.mode(Color.fromRGBO(0, 255, 0, 0.5), BlendMode.plus),
),
),
));

await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('invert_colors_test.1.png'),
skip: !Platform.isLinux,
);
});
}

// Draws a rectangle sized by the parent widget with [color], [colorFilter],
// and [invertColors] applied for testing the invert colors.
class InvertColorTestWidget extends LeafRenderObjectWidget {
const InvertColorTestWidget({
this.color,
this.filter,
Key key
}) : super(key: key);

final Color color;
final ColorFilter filter;

@override
RenderInvertColorTest createRenderObject(BuildContext context) {
return RenderInvertColorTest(color, filter);
}
@override
void updateRenderObject(BuildContext context, covariant RenderInvertColorTest renderObject) {
renderObject
..color = color
..filter = filter;
}

}

class RenderInvertColorTest extends RenderProxyBox {
RenderInvertColorTest(this._color, this._filter);

Color get color => _color;
Color _color;
set color(Color value) {
if (color == value)
return;
_color = value;
markNeedsPaint();
}


ColorFilter get filter => _filter;
ColorFilter _filter;
set filter(ColorFilter value) {
if (filter == value)
return;
_filter = value;
markNeedsPaint();
}

@override
void paint(PaintingContext context, Offset offset) {
final Paint paint = Paint()
..style = PaintingStyle.fill
..color = color
..colorFilter = filter
..invertColors = true;
context.canvas.drawRect(offset & size, paint);
}
}

0 comments on commit 23499f4

Please sign in to comment.