Unverified Commit 23499f40 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Fix typo in MediaQuery.fromWindow and add invertColors flag to images for smart invert. (#21457)

parent 5ea987db
......@@ -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.
///
......@@ -361,6 +366,7 @@ void paintImage({
Rect centerSlice,
ImageRepeat repeat = ImageRepeat.noRepeat,
bool flipHorizontally = false,
bool invertColors = false,
}) {
assert(canvas != null);
assert(image != null);
......@@ -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;
......
......@@ -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),
......@@ -52,6 +53,7 @@ class RenderImage extends RenderBox {
_repeat = repeat,
_centerSlice = centerSlice,
_matchTextDirection = matchTextDirection,
_invertColors = invertColors,
_textDirection = textDirection {
_updateColorFilter();
}
......@@ -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
......@@ -331,6 +347,7 @@ class RenderImage extends RenderBox {
centerSlice: _centerSlice,
repeat: _repeat,
flipHorizontally: _flipHorizontally,
invertColors: invertColors,
);
}
......@@ -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));
}
}
......@@ -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),
......@@ -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));
......@@ -4611,6 +4623,7 @@ class RawImage extends LeafRenderObjectWidget {
centerSlice: centerSlice,
matchTextDirection: matchTextDirection,
textDirection: matchTextDirection || alignment is! Alignment ? Directionality.of(context) : null,
invertColors: invertColors,
);
}
......@@ -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
......@@ -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));
}
}
......
......@@ -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';
......@@ -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))
......@@ -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;
......
......@@ -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;
......
......@@ -92,6 +92,7 @@ void main() {
' size: Size(25.0, 25.0)\n'
' image: [10×10]\n'
' alignment: center\n'
' invertColors: false\n'
),
);
......
// 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);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment