From e8d71b4d2ff02a7d83f2231b4cd2d0b33ed1f8eb Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Tue, 14 Apr 2020 12:25:03 -0400 Subject: [PATCH 01/39] Roll fuchsia/sdk/core/mac-amd64 from 8JtFK... to X4B0z... (#17701) --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 1af4d736d7562..965ca34b5f2ab 100644 --- a/DEPS +++ b/DEPS @@ -538,7 +538,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': '8JtFK64mmIC2zTEj9ICMrcQBITqKDZVQluLVKczro9kC' + 'version': 'X4B0z1QIDjf3vCQExTtBxxMoa8LYBKAwM8OBdqk80w4C' } ], 'condition': 'host_os == "mac"', From dfe13788edd495667bea89f45d6aa721d377abeb Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Tue, 14 Apr 2020 12:45:21 -0700 Subject: [PATCH 02/39] Adjust the GLFW build options (#17704) - Adds an explicit option for not building the GLFW embedding. - Disables GLFW by default on Windows, where it's no longer the uploaded embedding. - Moves the X11 pkg-config, which is only used by the GLFW embedding, behind the GLFW build flag. --- shell/platform/glfw/config.gni | 2 +- shell/platform/linux/config/BUILD.gn | 7 +++++-- tools/gn | 11 ++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/shell/platform/glfw/config.gni b/shell/platform/glfw/config.gni index 3e636c8239143..36e4b0f700540 100644 --- a/shell/platform/glfw/config.gni +++ b/shell/platform/glfw/config.gni @@ -9,5 +9,5 @@ declare_args() { # but it can be enabled for supported platforms (Windows, macOS, and Linux) # as an extra build artifact with this flag. The native toolkit shell will # still be built as well. - build_glfw_shell = (is_linux || is_win) && current_toolchain == host_toolchain + build_glfw_shell = is_linux && current_toolchain == host_toolchain } diff --git a/shell/platform/linux/config/BUILD.gn b/shell/platform/linux/config/BUILD.gn index d188f2dd6389b..16a8bbc860c9c 100644 --- a/shell/platform/linux/config/BUILD.gn +++ b/shell/platform/linux/config/BUILD.gn @@ -3,9 +3,12 @@ # found in the LICENSE file. import("//build/config/linux/pkg_config.gni") +import("//flutter/shell/platform/glfw/config.gni") -pkg_config("x11") { - packages = [ "x11" ] +if (build_glfw_shell) { + pkg_config("x11") { + packages = [ "x11" ] + } } pkg_config("gtk") { diff --git a/tools/gn b/tools/gn index 6d47127ca30fe..8856d691ad63f 100755 --- a/tools/gn +++ b/tools/gn @@ -250,9 +250,8 @@ def to_gn_args(args): gn_args['dart_platform_sdk'] = not args.full_dart_sdk gn_args['full_dart_sdk'] = args.full_dart_sdk - if sys.platform == 'darwin': - if args.build_glfw_shell: - gn_args['build_glfw_shell'] = True + if args.build_glfw_shell is not None: + gn_args['build_glfw_shell'] = args.build_glfw_shell gn_args['stripped_symbols'] = args.stripped @@ -340,8 +339,10 @@ def parse_args(args): help='The IDE files to generate using GN. Use `gn gen help` and look for the --ide flag to' + ' see supported IDEs. If this flag is not specified, a platform specific default is selected.') - parser.add_argument('--build-glfw-shell', dest='build_glfw_shell', default=False, action='store_true', - help='Force building the GLFW shell on desktop platforms where it is not built by default.') + parser.add_argument('--build-glfw-shell', action='store_const', const=True, + help='Build the GLFW shell on supported platforms where it is not built by default.') + parser.add_argument('--no-build-glfw-shell', dest='build_glfw_shell', action='store_const', const=False, + help='Do not build the GLFW shell on platforms where it is built by default.') parser.add_argument('--bitcode', default=False, action='store_true', help='Enable bitcode for iOS targets. On debug runtime modes, this will be a marker only.') From 1dabddf113f2d8c8ccab49820e884d82aa4d58ed Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Tue, 14 Apr 2020 17:20:01 -0400 Subject: [PATCH 03/39] Roll src/third_party/skia ad653d8378d7..44e2c5f0babc (9 commits) (#17709) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 965ca34b5f2ab..be8670e0e7fc3 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': 'ad653d8378d7a17502956c4addebb68eb3129961', + 'skia_revision': '44e2c5f0babca7ff824a65b615b4c2ac7e195470', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 8f0b0639ec3f7..1d54202a5146f 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 2da5a3733cfc3ee9d4098855a1f98d15 +Signature: caaa39a35d2a0fc07b167319cbd93823 UNUSED LICENSES: @@ -1070,6 +1070,8 @@ FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.ex FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian10-GCC-x86_64-Debug-Docker.json FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian10-GCC-x86_64-Release-NoGPU_Docker.json FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian10-GCC-x86_64-Release-Shared_Docker.json +FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-Clang-x86_64-Debug-Chromebook_GLES_Docker.json +FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-Clang-x86_64-Release-Chromebook_GLES_Docker.json FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Mac-Clang-arm-Debug-iOS.json FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Mac-Clang-arm64-Debug-Android_Vulkan.json FILE: ../../../third_party/skia/infra/bots/recipe_modules/build/examples/full.expected/Build-Mac-Clang-arm64-Debug-iOS.json @@ -1237,6 +1239,7 @@ FILE: ../../../third_party/skia/infra/canvaskit/docker/canvaskit-emsdk/Dockerfil FILE: ../../../third_party/skia/infra/config/recipes.cfg FILE: ../../../third_party/skia/infra/cross-compile/docker/cross-linux-arm64/Dockerfile FILE: ../../../third_party/skia/infra/cts/whitelist_devices.json +FILE: ../../../third_party/skia/infra/docker/debian9/Dockerfile FILE: ../../../third_party/skia/infra/gcc/Debian10-mips64el/Dockerfile FILE: ../../../third_party/skia/infra/gcc/Debian10-x86/Dockerfile FILE: ../../../third_party/skia/infra/gcc/Debian10/Dockerfile @@ -3914,11 +3917,17 @@ FILE: ../../../third_party/skia/src/gpu/d3d/GrD3DTypesPriv.cpp FILE: ../../../third_party/skia/src/gpu/d3d/GrD3DUtil.cpp FILE: ../../../third_party/skia/src/gpu/d3d/GrD3DUtil.h FILE: ../../../third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp +FILE: ../../../third_party/skia/src/gpu/effects/GrMatrixEffect.fp FILE: ../../../third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp FILE: ../../../third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h +FILE: ../../../third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp +FILE: ../../../third_party/skia/src/gpu/effects/generated/GrMatrixEffect.h +FILE: ../../../third_party/skia/src/gpu/glsl/GrGLSLUniformHandler.cpp FILE: ../../../third_party/skia/src/gpu/vk/GrVkManagedResource.h FILE: ../../../third_party/skia/src/sksl/SkSLSPIRVtoHLSL.cpp FILE: ../../../third_party/skia/src/sksl/SkSLSPIRVtoHLSL.h +FILE: ../../../third_party/skia/src/sksl/SkSLSampleMatrix.cpp +FILE: ../../../third_party/skia/src/sksl/SkSLSampleMatrix.h ---------------------------------------------------------------------------------------------------- Copyright 2020 Google LLC @@ -5033,6 +5042,8 @@ FILE: ../../../third_party/skia/gm/fpcoordinateoverride.cpp FILE: ../../../third_party/skia/gm/inverseclip.cpp FILE: ../../../third_party/skia/gm/labyrinth.cpp FILE: ../../../third_party/skia/gm/preservefillrule.cpp +FILE: ../../../third_party/skia/gm/sample_matrix_constant.cpp +FILE: ../../../third_party/skia/gm/sample_matrix_variable.cpp FILE: ../../../third_party/skia/gm/tilemodes_alpha.cpp FILE: ../../../third_party/skia/include/core/SkPathTypes.h FILE: ../../../third_party/skia/modules/skplaintexteditor/app/editor_application.cpp @@ -5627,6 +5638,8 @@ FILE: ../../../third_party/skia/src/core/SkColorFilterPriv.h FILE: ../../../third_party/skia/src/core/SkCompressedDataUtils.cpp FILE: ../../../third_party/skia/src/core/SkCompressedDataUtils.h FILE: ../../../third_party/skia/src/core/SkM44.cpp +FILE: ../../../third_party/skia/src/core/SkMarkerStack.cpp +FILE: ../../../third_party/skia/src/core/SkMarkerStack.h FILE: ../../../third_party/skia/src/core/SkVerticesPriv.h FILE: ../../../third_party/skia/src/gpu/GrDynamicAtlas.cpp FILE: ../../../third_party/skia/src/gpu/GrDynamicAtlas.h From 6d17ce60cb5da1c7f303f6205eabfec7dbb75515 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Tue, 14 Apr 2020 14:43:29 -0700 Subject: [PATCH 04/39] switched to using the ocmock build file in //build (#17707) --- DEPS | 2 +- shell/platform/darwin/ios/BUILD.gn | 90 +------------------ .../FlutterPluginAppLifeCycleDelegateTest.m | 2 +- .../Source/FlutterTextInputPluginTest.m | 2 +- .../framework/Source/SemanticsObjectTest.mm | 2 +- 5 files changed, 5 insertions(+), 93 deletions(-) diff --git a/DEPS b/DEPS index be8670e0e7fc3..aa99edf34ed88 100644 --- a/DEPS +++ b/DEPS @@ -139,7 +139,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + '036715c76da60220b39312ea066cd65d32c2157d', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '1b6a1b344074a1105b2e9b1c714766bace22acd7', # Fuchsia compatibility # diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 8fd88147c7e64..7f5870a043128 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -37,10 +37,6 @@ _flutter_framework_headers = [ _flutter_framework_headers_copy_dir = "$_flutter_framework_dir/Headers" -# TODO(54502): move this variable into //build/config/ios/ios_sdk.gni -# Version of iOS that we're targeting for tests. -ios_testing_deployment_target = "13.0" - source_set("flutter_framework_source") { visibility = [ ":*" ] cflags_objc = flutter_cflags_objc @@ -150,89 +146,6 @@ source_set("flutter_framework_source") { ] } -ocmock_path = "../../../../../third_party/ocmock/Source" - -# TODO(54503): Clone the OCMock repository so we can add a BUILD.gn to it. -static_library("ocmock") { - configs -= [ "//build/config/compiler:chromium_code" ] - cflags = [ - "-fvisibility=default", - "-mios-simulator-version-min=$ios_testing_deployment_target", - "-Wno-misleading-indentation", - ] - sources = [ - "$ocmock_path/OCMock/NSInvocation+OCMAdditions.h", - "$ocmock_path/OCMock/NSInvocation+OCMAdditions.m", - "$ocmock_path/OCMock/NSMethodSignature+OCMAdditions.h", - "$ocmock_path/OCMock/NSMethodSignature+OCMAdditions.m", - "$ocmock_path/OCMock/NSNotificationCenter+OCMAdditions.h", - "$ocmock_path/OCMock/NSNotificationCenter+OCMAdditions.m", - "$ocmock_path/OCMock/NSObject+OCMAdditions.h", - "$ocmock_path/OCMock/NSObject+OCMAdditions.m", - "$ocmock_path/OCMock/NSValue+OCMAdditions.h", - "$ocmock_path/OCMock/NSValue+OCMAdditions.m", - "$ocmock_path/OCMock/OCClassMockObject.h", - "$ocmock_path/OCMock/OCClassMockObject.m", - "$ocmock_path/OCMock/OCMArg.h", - "$ocmock_path/OCMock/OCMArg.m", - "$ocmock_path/OCMock/OCMArgAction.h", - "$ocmock_path/OCMock/OCMArgAction.m", - "$ocmock_path/OCMock/OCMBlockArgCaller.h", - "$ocmock_path/OCMock/OCMBlockArgCaller.m", - "$ocmock_path/OCMock/OCMBlockCaller.h", - "$ocmock_path/OCMock/OCMBlockCaller.m", - "$ocmock_path/OCMock/OCMBoxedReturnValueProvider.h", - "$ocmock_path/OCMock/OCMBoxedReturnValueProvider.m", - "$ocmock_path/OCMock/OCMConstraint.h", - "$ocmock_path/OCMock/OCMConstraint.m", - "$ocmock_path/OCMock/OCMExceptionReturnValueProvider.h", - "$ocmock_path/OCMock/OCMExceptionReturnValueProvider.m", - "$ocmock_path/OCMock/OCMExpectationRecorder.h", - "$ocmock_path/OCMock/OCMExpectationRecorder.m", - "$ocmock_path/OCMock/OCMFunctions.h", - "$ocmock_path/OCMock/OCMFunctions.m", - "$ocmock_path/OCMock/OCMFunctionsPrivate.h", - "$ocmock_path/OCMock/OCMIndirectReturnValueProvider.h", - "$ocmock_path/OCMock/OCMIndirectReturnValueProvider.m", - "$ocmock_path/OCMock/OCMInvocationExpectation.h", - "$ocmock_path/OCMock/OCMInvocationExpectation.m", - "$ocmock_path/OCMock/OCMInvocationMatcher.h", - "$ocmock_path/OCMock/OCMInvocationMatcher.m", - "$ocmock_path/OCMock/OCMInvocationStub.h", - "$ocmock_path/OCMock/OCMInvocationStub.m", - "$ocmock_path/OCMock/OCMLocation.h", - "$ocmock_path/OCMock/OCMLocation.m", - "$ocmock_path/OCMock/OCMMacroState.h", - "$ocmock_path/OCMock/OCMMacroState.m", - "$ocmock_path/OCMock/OCMNotificationPoster.h", - "$ocmock_path/OCMock/OCMNotificationPoster.m", - "$ocmock_path/OCMock/OCMObserverRecorder.h", - "$ocmock_path/OCMock/OCMObserverRecorder.m", - "$ocmock_path/OCMock/OCMPassByRefSetter.h", - "$ocmock_path/OCMock/OCMPassByRefSetter.m", - "$ocmock_path/OCMock/OCMRealObjectForwarder.h", - "$ocmock_path/OCMock/OCMRealObjectForwarder.m", - "$ocmock_path/OCMock/OCMRecorder.h", - "$ocmock_path/OCMock/OCMRecorder.m", - "$ocmock_path/OCMock/OCMReturnValueProvider.h", - "$ocmock_path/OCMock/OCMReturnValueProvider.m", - "$ocmock_path/OCMock/OCMStubRecorder.h", - "$ocmock_path/OCMock/OCMStubRecorder.m", - "$ocmock_path/OCMock/OCMVerifier.h", - "$ocmock_path/OCMock/OCMVerifier.m", - "$ocmock_path/OCMock/OCMock.h", - "$ocmock_path/OCMock/OCMockObject.h", - "$ocmock_path/OCMock/OCMockObject.m", - "$ocmock_path/OCMock/OCObserverMockObject.h", - "$ocmock_path/OCMock/OCObserverMockObject.m", - "$ocmock_path/OCMock/OCPartialMockObject.h", - "$ocmock_path/OCMock/OCPartialMockObject.m", - "$ocmock_path/OCMock/OCProtocolMockObject.h", - "$ocmock_path/OCMock/OCProtocolMockObject.m", - ] - include_dirs = [ "$ocmock_path" ] -} - ios_test_flutter_path = rebase_path("$root_out_dir/libios_test_flutter.dylib") platform_frameworks_path = "$ios_sdk_path/../../Library/Frameworks/" @@ -266,11 +179,10 @@ shared_library("ios_test_flutter") { ] deps = [ ":flutter_framework_source", - ":ocmock", "//flutter/shell/platform/darwin/common:framework_shared", + "//third_party/ocmock:ocmock", "//third_party/skia", ] - include_dirs = [ "$ocmock_path" ] public_configs = [ "//flutter:config" ] } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.m b/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.m index 4ce64acfc7793..2a5e053707b3b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.m @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import #import #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h" +#import "third_party/ocmock/Source/OCMock/OCMock.h" FLUTTER_ASSERT_ARC diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m index 6610d9fe4d8cd..5355e92fa3adc 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import #import #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" +#import "third_party/ocmock/Source/OCMock/OCMock.h" FLUTTER_ASSERT_ARC diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm index b067ee7920fc1..8ec62338ab825 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm @@ -1,8 +1,8 @@ -#import #import #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h" +#import "third_party/ocmock/Source/OCMock/OCMock.h" FLUTTER_ASSERT_ARC From 1192667a7a959b4744db92319ea99891d0ec303f Mon Sep 17 00:00:00 2001 From: Ferhat Date: Tue, 14 Apr 2020 15:40:16 -0700 Subject: [PATCH 05/39] [web] Fix extra canvas generation due to context access (#17710) * Fix extra canvas generation due to context access * add comment * address review comment --- lib/web_ui/lib/src/engine/bitmap_canvas.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/bitmap_canvas.dart b/lib/web_ui/lib/src/engine/bitmap_canvas.dart index e0ba89020de02..943d93d755e17 100644 --- a/lib/web_ui/lib/src/engine/bitmap_canvas.dart +++ b/lib/web_ui/lib/src/engine/bitmap_canvas.dart @@ -489,10 +489,11 @@ class BitmapCanvas extends EngineCanvas { @override void drawParagraph(EngineParagraph paragraph, ui.Offset offset) { assert(paragraph._isLaidOut); - html.CanvasRenderingContext2D ctx = _canvasPool.context; final ParagraphGeometricStyle style = paragraph._geometricStyle; if (paragraph._drawOnCanvas && _childOverdraw == false) { + // !Do not move this assignment above this if clause since, accessing + // context will generate extra tags. final List lines = paragraph._measurementResult.lines; final SurfacePaintData backgroundPaint = paragraph._background?.paintData; @@ -503,6 +504,7 @@ class BitmapCanvas extends EngineCanvas { } if (style != _cachedLastStyle) { + html.CanvasRenderingContext2D ctx = _canvasPool.context; ctx.font = style.cssFontString; _cachedLastStyle = style; } From e6a2534b63ac22d27981920de355789e268d43f0 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Tue, 14 Apr 2020 17:48:18 -0700 Subject: [PATCH 06/39] Add a gn flag to disable desktop embeddings (#17708) Desktop embedding dependencies can trigger gn-generation-time requiremenets; e.g., the Linux embeddings have pkg-config dependencies. This can be problematic in some build environments, such as building flutter_engine.so with a custom sysroot where those higher-level dependencies aren't available. This flag allows generating build files that don't have those dependencies. --- BUILD.gn | 38 ++++++++++++++++++++-------------- shell/platform/BUILD.gn | 18 +++++++--------- shell/platform/config.gni | 8 +++++++ shell/platform/darwin/BUILD.gn | 8 ++++--- tools/gn | 8 +++++++ 5 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 shell/platform/config.gni diff --git a/BUILD.gn b/BUILD.gn index fea2a2b5bebf1..74f58bfdad7a1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//flutter/common/config.gni") +import("//flutter/shell/platform/config.gni") if (is_fuchsia) { import("//build/fuchsia/sdk.gni") @@ -63,10 +64,8 @@ group("flutter") { # If on the host, compile all unittests targets. if (current_toolchain == host_toolchain) { if (is_mac) { - public_deps += [ - "//flutter/shell/platform/darwin:flutter_channels_unittests", - "//flutter/shell/platform/darwin/macos:flutter_desktop_darwin_unittests", - ] + public_deps += + [ "//flutter/shell/platform/darwin:flutter_channels_unittests" ] } public_deps += [ @@ -75,22 +74,11 @@ group("flutter") { "//flutter/lib/ui:ui_unittests", "//flutter/runtime:runtime_unittests", "//flutter/shell/common:shell_unittests", - "//flutter/shell/platform/common/cpp:common_cpp_core_unittests", - "//flutter/shell/platform/common/cpp:common_cpp_unittests", - "//flutter/shell/platform/common/cpp/client_wrapper:client_wrapper_unittests", "//flutter/shell/platform/embedder:embedder_unittests", - "//flutter/shell/platform/glfw/client_wrapper:client_wrapper_glfw_unittests", "//flutter/testing:testing_unittests", "//flutter/third_party/txt:txt_unittests", ] - if (is_win) { - public_deps += [ - "//flutter/shell/platform/windows:flutter_windows_unittests", - "//flutter/shell/platform/windows/client_wrapper:client_wrapper_windows_unittests", - ] - } - if (!is_win) { public_deps += [ "//flutter/fml:fml_benchmarks", @@ -98,6 +86,26 @@ group("flutter") { "//flutter/third_party/txt:txt_benchmarks", ] } + + # Unit tests for desktop embeddings should only be built if the desktop + # embeddings are being built. + if (enable_desktop_embeddings) { + public_deps += [ + "//flutter/shell/platform/common/cpp:common_cpp_core_unittests", + "//flutter/shell/platform/common/cpp:common_cpp_unittests", + "//flutter/shell/platform/common/cpp/client_wrapper:client_wrapper_unittests", + "//flutter/shell/platform/glfw/client_wrapper:client_wrapper_glfw_unittests", + ] + if (is_mac) { + public_deps += [ "//flutter/shell/platform/darwin/macos:flutter_desktop_darwin_unittests" ] + } + if (is_win) { + public_deps += [ + "//flutter/shell/platform/windows:flutter_windows_unittests", + "//flutter/shell/platform/windows/client_wrapper:client_wrapper_windows_unittests", + ] + } + } } } diff --git a/shell/platform/BUILD.gn b/shell/platform/BUILD.gn index 925177e67472b..d84a2ebbc5d4c 100644 --- a/shell/platform/BUILD.gn +++ b/shell/platform/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/fuchsia/sdk.gni") +import("//flutter/shell/platform/config.gni") group("platform") { if (is_mac || is_ios) { @@ -14,18 +15,15 @@ group("platform") { "android", ] } else if (is_linux) { - if (is_fuchsia_host) { - # The linux build is not supported as part of the Fuchsia host build. - deps = [] - } else { - deps = [ - "linux", - ] + deps = [] + if (enable_desktop_embeddings) { + deps += [ "linux" ] } } else if (is_win) { - deps = [ - "windows", - ] + deps = [] + if (enable_desktop_embeddings) { + deps += [ "windows" ] + } } else if (is_fuchsia) { deps = [ "fuchsia", diff --git a/shell/platform/config.gni b/shell/platform/config.gni new file mode 100644 index 0000000000000..3684094eb7927 --- /dev/null +++ b/shell/platform/config.gni @@ -0,0 +1,8 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +declare_args() { + # Whether or not to include desktop embedding targets in the build. + enable_desktop_embeddings = !is_fuchsia_host +} diff --git a/shell/platform/darwin/BUILD.gn b/shell/platform/darwin/BUILD.gn index bfc29dfe79d76..cace8efb9a887 100644 --- a/shell/platform/darwin/BUILD.gn +++ b/shell/platform/darwin/BUILD.gn @@ -4,6 +4,7 @@ assert(is_mac || is_ios) +import("//flutter/shell/platform/config.gni") import("//flutter/testing/testing.gni") group("darwin") { @@ -13,9 +14,10 @@ group("darwin") { ] } if (is_mac) { - deps = [ - "macos", - ] + deps = [] + if (enable_desktop_embeddings) { + deps += [ "macos" ] + } } } diff --git a/tools/gn b/tools/gn index 8856d691ad63f..6bdf3f74d0b14 100755 --- a/tools/gn +++ b/tools/gn @@ -250,6 +250,12 @@ def to_gn_args(args): gn_args['dart_platform_sdk'] = not args.full_dart_sdk gn_args['full_dart_sdk'] = args.full_dart_sdk + # Desktop embeddings can have more dependencies than the engine library, + # which can be problematic in some build environments (e.g., building on + # Linux will bring in pkg-config dependencies at generation time). These + # flags allow preventing those those targets from being part of the build + # tree. + gn_args['enable_desktop_embeddings'] = not args.disable_desktop_embeddings if args.build_glfw_shell is not None: gn_args['build_glfw_shell'] = args.build_glfw_shell @@ -339,6 +345,8 @@ def parse_args(args): help='The IDE files to generate using GN. Use `gn gen help` and look for the --ide flag to' + ' see supported IDEs. If this flag is not specified, a platform specific default is selected.') + parser.add_argument('--disable-desktop-embeddings', default=False, action='store_true', + help='Do not include desktop embeddings in the build.') parser.add_argument('--build-glfw-shell', action='store_const', const=True, help='Build the GLFW shell on supported platforms where it is not built by default.') parser.add_argument('--no-build-glfw-shell', dest='build_glfw_shell', action='store_const', const=False, From 7720ae7dd77a2c77898e081723e7d71d604e4c85 Mon Sep 17 00:00:00 2001 From: godofredoc <54371434+godofredoc@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:29:13 -0700 Subject: [PATCH 07/39] Updates to use predefined keys. (#17716) * Updates to use predefined keys. It starts using: * timeouts for paving. * timeouts for ssh commands. * timeouts for tests. https://github.com/flutter/flutter/issues/54416 * Update key location and autogenerate public key. * Use ssh-keygen instead of openssl. * Fix typo on test name. --- testing/fuchsia/run_tests.sh | 41 ++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/testing/fuchsia/run_tests.sh b/testing/fuchsia/run_tests.sh index 7fa6d38b68e77..452a064bc678e 100755 --- a/testing/fuchsia/run_tests.sh +++ b/testing/fuchsia/run_tests.sh @@ -10,12 +10,18 @@ # same directory as the script, as well as the `flutter_aot_runner-0.far` and # the `flutter_runner_tests-0.far`. It is written to be run from its own # directory, and will fail if run from other directories or via sym-links. +# +# This script also expects a private key available at: +# "/etc/botanist/keys/id_rsa_infra". set -Ee # The nodes are named blah-blah--four-word-fuchsia-id device_name=${SWARMING_BOT_ID#*--} +# Bot key to pave and ssh the device. +pkey="/etc/botanist/keys/id_rsa_infra" + if [ -z "$device_name" ] then echo "No device found. Aborting." @@ -28,21 +34,27 @@ reboot() { echo "Dumping system logs..." ./fuchsia_ctl -d $device_name ssh \ - -c "log_listener --dump_logs yes" + -c "log_listener --dump_logs yes" \ + --identity-file $pkey # note: this will set an exit code of 255, which we can ignore. - ./fuchsia_ctl -d $device_name ssh -c "dm reboot-recovery" || true + ./fuchsia_ctl -d $device_name ssh -c "dm reboot-recovery" \ + --identity-file $pkey || true } trap reboot EXIT echo "$(date) START:PAVING ------------------------------------------" -./fuchsia_ctl -d $device_name pave -i $1 +ssh-keygen -y -f $pkey > key.pub +./fuchsia_ctl -d $device_name pave -i $1 \ + --public-key "key.pub" echo "$(date) END:PAVING --------------------------------------------" echo "$(date) START:WAIT_DEVICE_READY -------------------------------" for i in {1..10}; do - ./fuchsia_ctl -d $device_name ssh -c "echo up" && break || sleep 15; + ./fuchsia_ctl -d $device_name ssh \ + --identity-file $pkey \ + -c "echo up" && break || sleep 15; done echo "$(date) END:WAIT_DEVICE_READY ---------------------------------" @@ -52,7 +64,9 @@ echo "$(date) START:flutter_runner_tests ----------------------------" ./fuchsia_ctl -d $device_name test \ -f flutter_aot_runner-0.far \ -f flutter_runner_tests-0.far \ - -t flutter_runner_tests + -t flutter_runner_tests \ + --identity-file $pkey \ + --timeout-seconds 300 # TODO(https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=47081) # Re-enable once the crash is resolved @@ -67,17 +81,23 @@ echo "$(date) START:fml_tests ---------------------------------------" ./fuchsia_ctl -d $device_name test \ -f fml_tests-0.far \ -t fml_tests \ - -a "--gtest_filter=-MessageLoop*:Message*:FileTest*" + -a "--gtest_filter=-MessageLoop*:Message*:FileTest*" \ + --identity-file $pkey \ + --timeout-seconds 300 echo "$(date) START:flow_tests --------------------------------------" ./fuchsia_ctl -d $device_name test \ -f flow_tests-0.far \ - -t flow_tests + -t flow_tests \ + --identity-file $pkey \ + --timeout-seconds 300 echo "$(date) START:runtime_tests -----------------------------------" ./fuchsia_ctl -d $device_name test \ -f runtime_tests-0.far \ - -t runtime_tests + -t runtime_tests \ + --identity-file $pkey \ + --timeout-seconds 300 # TODO(https://github.com/flutter/flutter/issues/53399): Re-enable # OnServiceProtocolGetSkSLsWorks and CanLoadSkSLsFromAsset once they pass on @@ -86,4 +106,7 @@ echo "$(date) START:shell_tests -------------------------------------" ./fuchsia_ctl -d $device_name test \ -f shell_tests-0.far \ -t shell_tests \ - -a "--gtest_filter=-ShellTest.CacheSkSLWorks:ShellTest.SetResourceCacheSize*:ShellTest.OnServiceProtocolGetSkSLsWorks:ShellTest.CanLoadSkSLsFromAsset" + -a "--gtest_filter=-ShellTest.CacheSkSLWorks:ShellTest.SetResourceCacheSize*:ShellTest.OnServiceProtocolGetSkSLsWorks:ShellTest.CanLoadSkSLsFromAsset" \ + --identity-file $pkey \ + --timeout-seconds 300 + From 04cfe7c253882942aedd20385899d0c47fd45529 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Tue, 14 Apr 2020 22:29:48 -0400 Subject: [PATCH 08/39] Roll fuchsia/sdk/core/linux-amd64 from LnaL2... to M1a9q... (#17715) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/fuchsia-linux-sdk-flutter-engine Please CC on the revert to ensure that a human is aware of the problem. To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md --- DEPS | 2 +- ci/licenses_golden/licenses_fuchsia | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index aa99edf34ed88..0cf5f58a4ff9f 100644 --- a/DEPS +++ b/DEPS @@ -558,7 +558,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'LnaL23_DpQsbnbs-byJi-UoGe1XerKCfLjb4_XkxMRoC' + 'version': 'M1a9qkxiTlatk7o1E8lede6K7dr5fnTSKcoGqW2SsBUC' } ], 'condition': 'host_os == "linux"', diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index 5e24346dc2215..7077ded728113 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: adc98c90de1d424da0f0546ff7689965 +Signature: 8b13b3b022828174f91e229cf515afa5 UNUSED LICENSES: @@ -3269,6 +3269,7 @@ FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.media/activity_reporter.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.media/profile_provider.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.memorypressure/memorypressure.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.modular/session/session_restart_controller.fidl +FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.net/socket.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.settings/night_mode.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.ui.input3/events.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.ui.input3/keyboard.fidl From dd87e3f944cf8dd6829149f7a480cd2d1869a1bc Mon Sep 17 00:00:00 2001 From: Yegor Date: Tue, 14 Apr 2020 20:08:10 -0700 Subject: [PATCH 09/39] Optimize static content scrolling (#17621) * store paint command bounds * do not apply commands outside the clip region * better cull rect prediction * enforce RecordingCanvas.endRecording --- lib/web_ui/lib/src/engine/bitmap_canvas.dart | 2 +- lib/web_ui/lib/src/engine/picture.dart | 6 +- .../lib/src/engine/surface/picture.dart | 59 ++-- .../src/engine/surface/recording_canvas.dart | 328 ++++++++++++++---- lib/web_ui/test/canvas_test.dart | 14 +- .../test/engine/recording_canvas_test.dart | 114 +++++- .../engine/canvas_blend_golden_test.dart | 3 +- .../engine/canvas_clip_path_test.dart | 3 +- .../engine/canvas_context_test.dart | 3 +- .../engine/canvas_draw_image_golden_test.dart | 3 +- .../engine/canvas_reuse_test.dart | 6 +- .../engine/conic_golden_test.dart | 3 +- .../engine/draw_vertices_golden_test.dart | 3 +- .../engine/linear_gradient_golden_test.dart | 3 +- .../multiline_text_clipping_golden_test.dart | 7 +- .../engine/path_metrics_test.dart | 3 +- .../engine/path_to_svg_golden_test.dart | 3 +- .../engine/path_transform_test.dart | 3 +- .../engine/radial_gradient_golden_test.dart | 3 +- .../engine/recording_canvas_golden_test.dart | 136 +++++--- lib/web_ui/test/mock_engine_canvas.dart | 5 +- 21 files changed, 533 insertions(+), 177 deletions(-) diff --git a/lib/web_ui/lib/src/engine/bitmap_canvas.dart b/lib/web_ui/lib/src/engine/bitmap_canvas.dart index 943d93d755e17..d9bd8fa25aef6 100644 --- a/lib/web_ui/lib/src/engine/bitmap_canvas.dart +++ b/lib/web_ui/lib/src/engine/bitmap_canvas.dart @@ -545,7 +545,7 @@ class BitmapCanvas extends EngineCanvas { /// Paints the [picture] into this canvas. void drawPicture(ui.Picture picture) { final EnginePicture enginePicture = picture; - enginePicture.recordingCanvas.apply(this); + enginePicture.recordingCanvas.apply(this, bounds); } /// Draws vertices on a gl context. diff --git a/lib/web_ui/lib/src/engine/picture.dart b/lib/web_ui/lib/src/engine/picture.dart index d88272cefc9ea..04010a28f27f4 100644 --- a/lib/web_ui/lib/src/engine/picture.dart +++ b/lib/web_ui/lib/src/engine/picture.dart @@ -32,6 +32,7 @@ class EnginePictureRecorder implements ui.PictureRecorder { return null; } _isRecording = false; + _canvas.endRecording(); return EnginePicture(_canvas, cullRect); } } @@ -46,8 +47,9 @@ class EnginePicture implements ui.Picture { @override Future toImage(int width, int height) async { - final BitmapCanvas canvas = BitmapCanvas(ui.Rect.fromLTRB(0, 0, width.toDouble(), height.toDouble())); - recordingCanvas.apply(canvas); + final ui.Rect imageRect = ui.Rect.fromLTRB(0, 0, width.toDouble(), height.toDouble()); + final BitmapCanvas canvas = BitmapCanvas(imageRect); + recordingCanvas.apply(canvas, imageRect); final String imageDataUrl = canvas.toDataUrl(); final html.ImageElement imageElement = html.ImageElement() ..src = imageDataUrl diff --git a/lib/web_ui/lib/src/engine/surface/picture.dart b/lib/web_ui/lib/src/engine/surface/picture.dart index c0a5f2198cc75..50d77b0560cc2 100644 --- a/lib/web_ui/lib/src/engine/surface/picture.dart +++ b/lib/web_ui/lib/src/engine/surface/picture.dart @@ -145,7 +145,7 @@ class PersistedHoudiniPicture extends PersistedPicture { _canvas = canvas; domRenderer.clearDom(rootElement); rootElement.append(_canvas.rootElement); - picture.recordingCanvas.apply(_canvas); + picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); canvas.commit(); } } @@ -231,7 +231,7 @@ class PersistedStandardPicture extends PersistedPicture { _canvas = DomCanvas(); domRenderer.clearDom(rootElement); rootElement.append(_canvas.rootElement); - picture.recordingCanvas.apply(_canvas); + picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); } void _applyBitmapPaint(EngineCanvas oldCanvas) { @@ -244,7 +244,7 @@ class PersistedStandardPicture extends PersistedPicture { oldCanvas.bounds = _optimalLocalCullRect; _canvas = oldCanvas; _canvas.clear(); - picture.recordingCanvas.apply(_canvas); + picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); } else { // We can't use the old canvas because the size has changed, so we put // it in a cache for later reuse. @@ -265,7 +265,7 @@ class PersistedStandardPicture extends PersistedPicture { domRenderer.clearDom(rootElement); rootElement.append(_canvas.rootElement); _canvas.clear(); - picture.recordingCanvas.apply(_canvas); + picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); }, )); } @@ -352,7 +352,7 @@ class PersistedStandardPicture extends PersistedPicture { /// to draw shapes and text. abstract class PersistedPicture extends PersistedLeafSurface { PersistedPicture(this.dx, this.dy, this.picture, this.hints) - : localPaintBounds = picture.recordingCanvas.computePaintBounds(); + : localPaintBounds = picture.recordingCanvas.pictureBounds; EngineCanvas _canvas; @@ -491,7 +491,7 @@ abstract class PersistedPicture extends PersistedLeafSurface { // The new cull rect contains area not covered by a previous rect. Perhaps // the clip is growing, moving around the picture, or both. In this case - // a part of the picture may not been painted. We will need to + // a part of the picture may not have been painted. We will need to // request a new canvas and paint the picture on it. However, this is also // a strong signal that the clip will continue growing as typically // Flutter uses animated transitions. So instead of allocating the canvas @@ -500,25 +500,19 @@ abstract class PersistedPicture extends PersistedLeafSurface { // will hit the above case where the new cull rect is fully contained // within the cull rect we compute now. - // If any of the borders moved. - // TODO(yjbanov): consider switching to Mouad's snap-to-10px strategy. It - // might be sufficient, if not more effective. - const double kPredictedGrowthFactor = 3.0; - final double leftwardTrend = kPredictedGrowthFactor * - math.max(oldOptimalLocalCullRect.left - _exactLocalCullRect.left, 0); - final double upwardTrend = kPredictedGrowthFactor * - math.max(oldOptimalLocalCullRect.top - _exactLocalCullRect.top, 0); - final double rightwardTrend = kPredictedGrowthFactor * - math.max(_exactLocalCullRect.right - oldOptimalLocalCullRect.right, 0); - final double bottomwardTrend = kPredictedGrowthFactor * - math.max( - _exactLocalCullRect.bottom - oldOptimalLocalCullRect.bottom, 0); + // Compute the delta, by which each of the side of the clip rect has "moved" + // since the last time we updated the cull rect. + final double leftwardDelta = oldOptimalLocalCullRect.left - _exactLocalCullRect.left; + final double upwardDelta = oldOptimalLocalCullRect.top - _exactLocalCullRect.top; + final double rightwardDelta = _exactLocalCullRect.right - oldOptimalLocalCullRect.right; + final double bottomwardDelta = _exactLocalCullRect.bottom - oldOptimalLocalCullRect.bottom; + // Compute the new optimal rect to paint into. final ui.Rect newLocalCullRect = ui.Rect.fromLTRB( - oldOptimalLocalCullRect.left - leftwardTrend, - oldOptimalLocalCullRect.top - upwardTrend, - oldOptimalLocalCullRect.right + rightwardTrend, - oldOptimalLocalCullRect.bottom + bottomwardTrend, + _exactLocalCullRect.left - _predictTrend(leftwardDelta, _exactLocalCullRect.width), + _exactLocalCullRect.top - _predictTrend(upwardDelta, _exactLocalCullRect.height), + _exactLocalCullRect.right + _predictTrend(rightwardDelta, _exactLocalCullRect.width), + _exactLocalCullRect.bottom + _predictTrend(bottomwardDelta, _exactLocalCullRect.height), ).intersect(localPaintBounds); final bool localCullRectChanged = _optimalLocalCullRect != newLocalCullRect; @@ -526,6 +520,25 @@ abstract class PersistedPicture extends PersistedLeafSurface { return localCullRectChanged; } + /// Predicts the delta a particular side of a clip rect will move given the + /// [delta] it moved by last, and the respective [extent] (width or height) + /// of the clip. + static double _predictTrend(double delta, double extent) { + if (delta <= 0.0) { + // Shrinking. Give it 10% of the extent in case the trend is reversed. + return extent * 0.1; + } else { + // Growing. Predict 10 more frames of similar deltas. Give it at least + // 50% of the extent (protect from extremely slow growth trend such as + // slow scrolling). Give no more than the full extent (protects from + // fast scrolling that could lead to overallocation). + return math.min( + math.max(extent * 0.5, delta * 10.0), + extent, + ); + } + } + /// Number of bitmap pixel painted by this picture. /// /// If the implementation does not paint onto a bitmap canvas, it should diff --git a/lib/web_ui/lib/src/engine/surface/recording_canvas.dart b/lib/web_ui/lib/src/engine/surface/recording_canvas.dart index 5b26210ae2af2..bb3f570450e94 100644 --- a/lib/web_ui/lib/src/engine/surface/recording_canvas.dart +++ b/lib/web_ui/lib/src/engine/surface/recording_canvas.dart @@ -23,10 +23,33 @@ double _measureBorderRadius(double x, double y) { /// /// See [Canvas] for docs for these methods. class RecordingCanvas { - /// Maximum paintable bounds for this canvas. + /// Computes [_pictureBounds]. final _PaintBounds _paintBounds; + + /// Maximum paintable bounds for the picture painted by this recording. + /// + /// The bounds contain the full picture. The commands recorded for the picture + /// are later pruned based on the clip applied to the picture. See the [apply] + /// method for more details. + ui.Rect get pictureBounds { + assert( + _debugRecordingEnded, + 'Picture bounds not available yet. Call [endRecording] before accessing picture bounds.', + ); + return _pictureBounds; + } + ui.Rect _pictureBounds; + final List _commands = []; + /// In debug mode returns the list of recorded paint commands for testing. + List get debugPaintCommands { + if (assertionsEnabled) { + return _commands; + } + throw UnsupportedError('For debugging only.'); + } + RecordingCanvas(ui.Rect bounds) : _paintBounds = _PaintBounds(bounds); /// Whether this canvas is doing arbitrary paint operations not expressible @@ -53,30 +76,78 @@ class RecordingCanvas { bool get didDraw => _didDraw; bool _didDraw = false; - /// Computes paint bounds based on estimated [bounds] and transforms. - ui.Rect computePaintBounds() { - return _paintBounds.computeBounds(); + /// When assertions are enabled used to ensure that [endRecording] is called + /// before calling [apply] or [pictureBounds]. + bool _debugRecordingEnded = false; + + /// Stops recording drawing commands and computes paint bounds. + /// + /// This must be called prior to passing the picture to the [SceneBuilder] + /// for rendering. In a production app, this is done automatically by + /// [PictureRecorder] when the framework calls [PictureRecorder.endRecording]. + /// However, if you are writing a unit-test and using [RecordingCanvas] + /// directly it is up to you to call this method explicitly. + void endRecording() { + _pictureBounds = _paintBounds.computeBounds(); + if (assertionsEnabled) { + _debugRecordingEnded = true; + } } /// Applies the recorded commands onto an [engineCanvas]. - void apply(EngineCanvas engineCanvas) { + /// + /// The [clipRect] specifies the clip applied to the picture (screen clip at + /// a minimum). The commands that fall outside the clip are skipped and are + /// not applied to the [engineCanvas]. A command must have a non-zero + /// intersection with the clip in order to be applied. + void apply(EngineCanvas engineCanvas, ui.Rect clipRect) { + assert(_debugRecordingEnded); if (_debugDumpPaintCommands) { final StringBuffer debugBuf = StringBuffer(); + int skips = 0; debugBuf.writeln( '--- Applying RecordingCanvas to ${engineCanvas.runtimeType} ' - 'with bounds $_paintBounds'); + 'with bounds $_paintBounds and clip $clipRect (w = ${clipRect.width},' + ' h = ${clipRect.height})'); for (int i = 0; i < _commands.length; i++) { final PaintCommand command = _commands[i]; + if (command is DrawCommand) { + if (command.isInvisible(clipRect)) { + // The drawing command is outside the clip region. No need to apply. + debugBuf.writeln('SKIPPED: ctx.$command;'); + skips += 1; + continue; + } + } debugBuf.writeln('ctx.$command;'); command.apply(engineCanvas); } + if (skips > 0) { + debugBuf.writeln('Total commands skipped: $skips'); + } debugBuf.writeln('--- End of command stream'); print(debugBuf); } else { try { - for (int i = 0, len = _commands.length; i < len; i++) { - PaintCommand command = _commands[i]; - command.apply(engineCanvas); + if (rectContainsOther(clipRect, _pictureBounds)) { + // No need to check if commands fit in the clip rect if we already + // know that the entire picture fits it. + for (int i = 0, len = _commands.length; i < len; i++) { + _commands[i].apply(engineCanvas); + } + } else { + // The picture doesn't fit the clip rect. Check that drawing commands + // fit before applying them. + for (int i = 0, len = _commands.length; i < len; i++) { + final PaintCommand command = _commands[i]; + if (command is DrawCommand) { + if (command.isInvisible(clipRect)) { + // The drawing command is outside the clip region. No need to apply. + continue; + } + } + command.apply(engineCanvas); + } } } catch (e) { // commands should never fail, but... @@ -103,12 +174,14 @@ class RecordingCanvas { } void save() { + assert(!_debugRecordingEnded); _paintBounds.saveTransformsAndClip(); _commands.add(const PaintSave()); _saveCount++; } void saveLayerWithoutBounds(SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; // TODO(het): Implement this correctly using another canvas. _commands.add(const PaintSave()); @@ -117,6 +190,7 @@ class RecordingCanvas { } void saveLayer(ui.Rect bounds, SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; // TODO(het): Implement this correctly using another canvas. _commands.add(const PaintSave()); @@ -125,6 +199,7 @@ class RecordingCanvas { } void restore() { + assert(!_debugRecordingEnded); _paintBounds.restoreTransformsAndClip(); if (_commands.isNotEmpty && _commands.last is PaintSave) { // A restore followed a save without any drawing operations in between. @@ -139,56 +214,71 @@ class RecordingCanvas { } void translate(double dx, double dy) { + assert(!_debugRecordingEnded); _paintBounds.translate(dx, dy); _commands.add(PaintTranslate(dx, dy)); } void scale(double sx, double sy) { + assert(!_debugRecordingEnded); _paintBounds.scale(sx, sy); _commands.add(PaintScale(sx, sy)); } void rotate(double radians) { + assert(!_debugRecordingEnded); _paintBounds.rotateZ(radians); _commands.add(PaintRotate(radians)); } void transform(Float64List matrix4) { + assert(!_debugRecordingEnded); _paintBounds.transform(matrix4); _commands.add(PaintTransform(matrix4)); } void skew(double sx, double sy) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _paintBounds.skew(sx, sy); _commands.add(PaintSkew(sx, sy)); } void clipRect(ui.Rect rect) { - _paintBounds.clipRect(rect); + assert(!_debugRecordingEnded); + final PaintClipRect command = PaintClipRect(rect); + _paintBounds.clipRect(rect, command); _hasArbitraryPaint = true; - _commands.add(PaintClipRect(rect)); + _commands.add(command); } void clipRRect(ui.RRect rrect) { - _paintBounds.clipRect(rrect.outerRect); + assert(!_debugRecordingEnded); + final PaintClipRRect command = PaintClipRRect(rrect); + _paintBounds.clipRect(rrect.outerRect, command); _hasArbitraryPaint = true; - _commands.add(PaintClipRRect(rrect)); + _commands.add(command); } void clipPath(ui.Path path, {bool doAntiAlias = true}) { - _paintBounds.clipRect(path.getBounds()); + assert(!_debugRecordingEnded); + final PaintClipPath command = PaintClipPath(path); + _paintBounds.clipRect(path.getBounds(), command); _hasArbitraryPaint = true; - _commands.add(PaintClipPath(path)); + _commands.add(command); } void drawColor(ui.Color color, ui.BlendMode blendMode) { - _paintBounds.grow(_paintBounds.maxPaintBounds); - _commands.add(PaintDrawColor(color, blendMode)); + assert(!_debugRecordingEnded); + final PaintDrawColor command = PaintDrawColor(color, blendMode); + _commands.add(command); + _paintBounds.grow(_paintBounds.maxPaintBounds, command); } void drawLine(ui.Offset p1, ui.Offset p2, SurfacePaint paint) { + assert(!_debugRecordingEnded); final double paintSpread = math.max(_getPaintSpread(paint), 1.0); + final PaintDrawLine command = PaintDrawLine(p1, p2, paint.paintData); // TODO(yjbanov): This can be optimized. Currently we create a box around // the line and then apply the transform on the box to get // the bounding box. If you have a 45-degree line and a @@ -201,34 +291,40 @@ class RecordingCanvas { math.min(p1.dy, p2.dy) - paintSpread, math.max(p1.dx, p2.dx) + paintSpread, math.max(p1.dy, p2.dy) + paintSpread, + command, ); _hasArbitraryPaint = true; _didDraw = true; - _commands.add(PaintDrawLine(p1, p2, paint.paintData)); + _commands.add(command); } void drawPaint(SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; - _paintBounds.grow(_paintBounds.maxPaintBounds); - _commands.add(PaintDrawPaint(paint.paintData)); + final PaintDrawPaint command = PaintDrawPaint(paint.paintData); + _paintBounds.grow(_paintBounds.maxPaintBounds, command); + _commands.add(command); } void drawRect(ui.Rect rect, SurfacePaint paint) { + assert(!_debugRecordingEnded); if (paint.shader != null) { _hasArbitraryPaint = true; } _didDraw = true; final double paintSpread = _getPaintSpread(paint); + final PaintDrawRect command = PaintDrawRect(rect, paint.paintData); if (paintSpread != 0.0) { - _paintBounds.grow(rect.inflate(paintSpread)); + _paintBounds.grow(rect.inflate(paintSpread), command); } else { - _paintBounds.grow(rect); + _paintBounds.grow(rect, command); } - _commands.add(PaintDrawRect(rect, paint.paintData)); + _commands.add(command); } void drawRRect(ui.RRect rrect, SurfacePaint paint) { + assert(!_debugRecordingEnded); if (paint.shader != null || !rrect.webOnlyUniformRadii) { _hasArbitraryPaint = true; } @@ -238,11 +334,13 @@ class RecordingCanvas { final double top = math.min(rrect.top, rrect.bottom) - paintSpread; final double right = math.max(rrect.left, rrect.right) + paintSpread; final double bottom = math.max(rrect.top, rrect.bottom) + paintSpread; - _paintBounds.growLTRB(left, top, right, bottom); - _commands.add(PaintDrawRRect(rrect, paint.paintData)); + final PaintDrawRRect command = PaintDrawRRect(rrect, paint.paintData); + _paintBounds.growLTRB(left, top, right, bottom, command); + _commands.add(command); } void drawDRRect(ui.RRect outer, ui.RRect inner, SurfacePaint paint) { + assert(!_debugRecordingEnded); // Check the inner bounds are contained within the outer bounds // see: https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkCanvas.cpp?l=1787-1789 ui.Rect innerRect = inner.outerRect; @@ -283,41 +381,50 @@ class RecordingCanvas { _hasArbitraryPaint = true; _didDraw = true; final double paintSpread = _getPaintSpread(paint); + final PaintDrawDRRect command = PaintDrawDRRect(outer, inner, paint.paintData); _paintBounds.growLTRB( outer.left - paintSpread, outer.top - paintSpread, outer.right + paintSpread, outer.bottom + paintSpread, + command, ); - _commands.add(PaintDrawDRRect(outer, inner, paint.paintData)); + _commands.add(command); } void drawOval(ui.Rect rect, SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; final double paintSpread = _getPaintSpread(paint); + final PaintDrawOval command = PaintDrawOval(rect, paint.paintData); if (paintSpread != 0.0) { - _paintBounds.grow(rect.inflate(paintSpread)); + _paintBounds.grow(rect.inflate(paintSpread), command); } else { - _paintBounds.grow(rect); + _paintBounds.grow(rect, command); } - _commands.add(PaintDrawOval(rect, paint.paintData)); + _commands.add(command); } void drawCircle(ui.Offset c, double radius, SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; final double paintSpread = _getPaintSpread(paint); + final PaintDrawCircle command = PaintDrawCircle(c, radius, paint.paintData); + final double distance = radius + paintSpread; _paintBounds.growLTRB( - c.dx - radius - paintSpread, - c.dy - radius - paintSpread, - c.dx + radius + paintSpread, - c.dy + radius + paintSpread, + c.dx - distance, + c.dy - distance, + c.dx + distance, + c.dy + distance, + command, ); - _commands.add(PaintDrawCircle(c, radius, paint.paintData)); + _commands.add(command); } void drawPath(ui.Path path, SurfacePaint paint) { + assert(!_debugRecordingEnded); if (paint.shader == null) { // For Rect/RoundedRect paths use drawRect/drawRRect code paths for // DomCanvas optimization. @@ -340,31 +447,37 @@ class RecordingCanvas { if (paintSpread != 0.0) { pathBounds = pathBounds.inflate(paintSpread); } - _paintBounds.grow(pathBounds); // Clone path so it can be reused for subsequent draw calls. final ui.Path clone = SurfacePath._shallowCopy(path); + final PaintDrawPath command = PaintDrawPath(clone, paint.paintData); + _paintBounds.grow(pathBounds, command); clone.fillType = path.fillType; - _commands.add(PaintDrawPath(clone, paint.paintData)); + _commands.add(command); } void drawImage(ui.Image image, ui.Offset offset, SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; final double left = offset.dx; final double top = offset.dy; - _paintBounds.growLTRB(left, top, left + image.width, top + image.height); - _commands.add(PaintDrawImage(image, offset, paint.paintData)); + final command = PaintDrawImage(image, offset, paint.paintData); + _paintBounds.growLTRB(left, top, left + image.width, top + image.height, command); + _commands.add(command); } void drawImageRect( ui.Image image, ui.Rect src, ui.Rect dst, SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; - _paintBounds.grow(dst); - _commands.add(PaintDrawImageRect(image, src, dst, paint.paintData)); + final PaintDrawImageRect command = PaintDrawImageRect(image, src, dst, paint.paintData); + _paintBounds.grow(dst, command); + _commands.add(command); } void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { + assert(!_debugRecordingEnded); final EngineParagraph engineParagraph = paragraph; if (!engineParagraph._isLaidOut) { // Ignore non-laid out paragraphs. This matches Flutter's behavior. @@ -377,42 +490,53 @@ class RecordingCanvas { } final double left = offset.dx; final double top = offset.dy; + final PaintDrawParagraph command = PaintDrawParagraph(engineParagraph, offset); _paintBounds.growLTRB( - left, top, left + engineParagraph.width, top + engineParagraph.height); - _commands.add(PaintDrawParagraph(engineParagraph, offset)); + left, + top, + left + engineParagraph.width, + top + engineParagraph.height, + command, + ); + _commands.add(command); } void drawShadow(ui.Path path, ui.Color color, double elevation, bool transparentOccluder) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; final ui.Rect shadowRect = computePenumbraBounds(path.getBounds(), elevation); - _paintBounds.grow(shadowRect); - _commands.add(PaintDrawShadow(path, color, elevation, transparentOccluder)); + final PaintDrawShadow command = PaintDrawShadow(path, color, elevation, transparentOccluder); + _paintBounds.grow(shadowRect, command); + _commands.add(command); } void drawVertices( ui.Vertices vertices, ui.BlendMode blendMode, SurfacePaint paint) { + assert(!_debugRecordingEnded); _hasArbitraryPaint = true; _didDraw = true; - _growPaintBoundsByPoints(vertices.positions, 0, paint); - _commands.add(PaintVertices(vertices, blendMode, paint.paintData)); + final PaintDrawVertices command = PaintDrawVertices(vertices, blendMode, paint.paintData); + _growPaintBoundsByPoints(vertices.positions, 0, paint, command); + _commands.add(command); } void drawRawPoints( ui.PointMode pointMode, Float32List points, SurfacePaint paint) { + assert(!_debugRecordingEnded); if (paint.strokeWidth == null) { return; } _hasArbitraryPaint = true; _didDraw = true; - _growPaintBoundsByPoints(points, paint.strokeWidth, paint); - _commands - .add(PaintPoints(pointMode, points, paint.strokeWidth, paint.color)); + final PaintDrawPoints command = PaintDrawPoints(pointMode, points, paint.strokeWidth, paint.color); + _growPaintBoundsByPoints(points, paint.strokeWidth, paint, command); + _commands.add(command); } - void _growPaintBoundsByPoints(Float32List points, double thickness, SurfacePaint paint) { + void _growPaintBoundsByPoints(Float32List points, double thickness, SurfacePaint paint, DrawCommand command) { double minValueX, maxValueX, minValueY, maxValueY; minValueX = maxValueX = points[0]; minValueY = maxValueY = points[1]; @@ -436,6 +560,7 @@ class RecordingCanvas { minValueY - distance - paintSpread, maxValueX + distance + paintSpread, maxValueY + distance + paintSpread, + command, ); } @@ -458,6 +583,43 @@ abstract class PaintCommand { void serializeToCssPaint(List> serializedCommands); } +/// A [PaintCommand] that affect pixels on the screen (unlike, for example, the +/// [SaveCommand]). +abstract class DrawCommand extends PaintCommand { + /// Whether the command is completely clipped out of the picture. + bool isClippedOut = false; + + /// The left bound of the graphic produced by this command in picture-global + /// coordinates. + double leftBound = double.negativeInfinity; + + /// The top bound of the graphic produced by this command in picture-global + /// coordinates. + double topBound = double.negativeInfinity; + + /// The right bound of the graphic produced by this command in picture-global + /// coordinates. + double rightBound = double.infinity; + + /// The bottom bound of the graphic produced by this command in + /// picture-global coordinates. + double bottomBound = double.infinity; + + /// Whether this command intersects with the [clipRect]. + bool isInvisible(ui.Rect clipRect) { + if (isClippedOut) { + return true; + } + + // Check top and bottom first because vertical scrolling is more common + // than horizontal scrolling. + return bottomBound < clipRect.top || + topBound > clipRect.bottom || + rightBound < clipRect.left || + leftBound > clipRect.right; + } +} + class PaintSave extends PaintCommand { const PaintSave(); @@ -632,7 +794,7 @@ class PaintSkew extends PaintCommand { } } -class PaintClipRect extends PaintCommand { +class PaintClipRect extends DrawCommand { final ui.Rect rect; PaintClipRect(this.rect); @@ -657,7 +819,7 @@ class PaintClipRect extends PaintCommand { } } -class PaintClipRRect extends PaintCommand { +class PaintClipRRect extends DrawCommand { final ui.RRect rrect; PaintClipRRect(this.rrect); @@ -685,7 +847,7 @@ class PaintClipRRect extends PaintCommand { } } -class PaintClipPath extends PaintCommand { +class PaintClipPath extends DrawCommand { final SurfacePath path; PaintClipPath(this.path); @@ -710,7 +872,7 @@ class PaintClipPath extends PaintCommand { } } -class PaintDrawColor extends PaintCommand { +class PaintDrawColor extends DrawCommand { final ui.Color color; final ui.BlendMode blendMode; @@ -737,7 +899,7 @@ class PaintDrawColor extends PaintCommand { } } -class PaintDrawLine extends PaintCommand { +class PaintDrawLine extends DrawCommand { final ui.Offset p1; final ui.Offset p2; final SurfacePaintData paint; @@ -771,7 +933,7 @@ class PaintDrawLine extends PaintCommand { } } -class PaintDrawPaint extends PaintCommand { +class PaintDrawPaint extends DrawCommand { final SurfacePaintData paint; PaintDrawPaint(this.paint); @@ -796,11 +958,11 @@ class PaintDrawPaint extends PaintCommand { } } -class PaintVertices extends PaintCommand { +class PaintDrawVertices extends DrawCommand { final ui.Vertices vertices; final ui.BlendMode blendMode; final SurfacePaintData paint; - PaintVertices(this.vertices, this.blendMode, this.paint); + PaintDrawVertices(this.vertices, this.blendMode, this.paint); @override void apply(EngineCanvas canvas) { @@ -822,12 +984,12 @@ class PaintVertices extends PaintCommand { } } -class PaintPoints extends PaintCommand { +class PaintDrawPoints extends DrawCommand { final Float32List points; final ui.PointMode pointMode; final double strokeWidth; final ui.Color color; - PaintPoints(this.pointMode, this.points, this.strokeWidth, this.color); + PaintDrawPoints(this.pointMode, this.points, this.strokeWidth, this.color); @override void apply(EngineCanvas canvas) { @@ -849,7 +1011,7 @@ class PaintPoints extends PaintCommand { } } -class PaintDrawRect extends PaintCommand { +class PaintDrawRect extends DrawCommand { final ui.Rect rect; final SurfacePaintData paint; @@ -879,7 +1041,7 @@ class PaintDrawRect extends PaintCommand { } } -class PaintDrawRRect extends PaintCommand { +class PaintDrawRRect extends DrawCommand { final ui.RRect rrect; final SurfacePaintData paint; @@ -909,7 +1071,7 @@ class PaintDrawRRect extends PaintCommand { } } -class PaintDrawDRRect extends PaintCommand { +class PaintDrawDRRect extends DrawCommand { final ui.RRect outer; final ui.RRect inner; final SurfacePaintData paint; @@ -941,7 +1103,7 @@ class PaintDrawDRRect extends PaintCommand { } } -class PaintDrawOval extends PaintCommand { +class PaintDrawOval extends DrawCommand { final ui.Rect rect; final SurfacePaintData paint; @@ -971,7 +1133,7 @@ class PaintDrawOval extends PaintCommand { } } -class PaintDrawCircle extends PaintCommand { +class PaintDrawCircle extends DrawCommand { final ui.Offset c; final double radius; final SurfacePaintData paint; @@ -1004,7 +1166,7 @@ class PaintDrawCircle extends PaintCommand { } } -class PaintDrawPath extends PaintCommand { +class PaintDrawPath extends DrawCommand { final SurfacePath path; final SurfacePaintData paint; @@ -1034,7 +1196,7 @@ class PaintDrawPath extends PaintCommand { } } -class PaintDrawShadow extends PaintCommand { +class PaintDrawShadow extends DrawCommand { PaintDrawShadow( this.path, this.color, this.elevation, this.transparentOccluder); @@ -1074,7 +1236,7 @@ class PaintDrawShadow extends PaintCommand { } } -class PaintDrawImage extends PaintCommand { +class PaintDrawImage extends DrawCommand { final ui.Image image; final ui.Offset offset; final SurfacePaintData paint; @@ -1103,7 +1265,7 @@ class PaintDrawImage extends PaintCommand { } } -class PaintDrawImageRect extends PaintCommand { +class PaintDrawImageRect extends DrawCommand { final ui.Image image; final ui.Rect src; final ui.Rect dst; @@ -1133,7 +1295,7 @@ class PaintDrawImageRect extends PaintCommand { } } -class PaintDrawParagraph extends PaintCommand { +class PaintDrawParagraph extends DrawCommand { final EngineParagraph paragraph; final ui.Offset offset; @@ -1765,7 +1927,7 @@ class _PaintBounds { _currentMatrix.multiply(skewMatrix); } - void clipRect(ui.Rect rect) { + void clipRect(ui.Rect rect, DrawCommand command) { // If we have an active transform, calculate screen relative clipping // rectangle and union with current clipping rectangle. if (!_currentMatrixIsIdentity) { @@ -1807,16 +1969,25 @@ class _PaintBounds { _currentClipBottom = rect.bottom; } } + if (_currentClipLeft >= _currentClipRight || _currentClipTop >= _currentClipBottom) { + command.isClippedOut = true; + } else { + command.leftBound = _currentClipLeft; + command.topBound = _currentClipTop; + command.rightBound = _currentClipRight; + command.bottomBound = _currentClipBottom; + } } /// Grow painted area to include given rectangle. - void grow(ui.Rect r) { - growLTRB(r.left, r.top, r.right, r.bottom); + void grow(ui.Rect r, DrawCommand command) { + growLTRB(r.left, r.top, r.right, r.bottom, command); } /// Grow painted area to include given rectangle. - void growLTRB(double left, double top, double right, double bottom) { + void growLTRB(double left, double top, double right, double bottom, DrawCommand command) { if (left == right || top == bottom) { + command.isClippedOut = true; return; } @@ -1836,15 +2007,19 @@ class _PaintBounds { if (_clipRectInitialized) { if (transformedPointLeft > _currentClipRight) { + command.isClippedOut = true; return; } if (transformedPointRight < _currentClipLeft) { + command.isClippedOut = true; return; } if (transformedPointTop > _currentClipBottom) { + command.isClippedOut = true; return; } if (transformedPointBottom < _currentClipTop) { + command.isClippedOut = true; return; } if (transformedPointLeft < _currentClipLeft) { @@ -1861,6 +2036,11 @@ class _PaintBounds { } } + command.leftBound = transformedPointLeft; + command.topBound = transformedPointTop; + command.rightBound = transformedPointRight; + command.bottomBound = transformedPointBottom; + if (_didPaintInsideClipArea) { _left = math.min( math.min(_left, transformedPointLeft), transformedPointRight); diff --git a/lib/web_ui/test/canvas_test.dart b/lib/web_ui/test/canvas_test.dart index ce9d1499caca2..cb7bcd2fbcf57 100644 --- a/lib/web_ui/test/canvas_test.dart +++ b/lib/web_ui/test/canvas_test.dart @@ -36,16 +36,17 @@ void main() { } testCanvas('draws laid out paragraph', (EngineCanvas canvas) { - final RecordingCanvas recordingCanvas = - RecordingCanvas(const ui.Rect.fromLTWH(0, 0, 100, 100)); + final ui.Rect screenRect = const ui.Rect.fromLTWH(0, 0, 100, 100); + final RecordingCanvas recordingCanvas = RecordingCanvas(screenRect); final ui.ParagraphBuilder builder = ui.ParagraphBuilder(ui.ParagraphStyle()); builder.addText('sample'); paragraph = builder.build(); paragraph.layout(const ui.ParagraphConstraints(width: 100)); recordingCanvas.drawParagraph(paragraph, const ui.Offset(10, 10)); + recordingCanvas.endRecording(); canvas.clear(); - recordingCanvas.apply(canvas); + recordingCanvas.apply(canvas, screenRect); }, whenDone: () { expect(mockCanvas.methodCallLog, hasLength(3)); @@ -60,15 +61,16 @@ void main() { testCanvas('ignores paragraphs that were not laid out', (EngineCanvas canvas) { - final RecordingCanvas recordingCanvas = - RecordingCanvas(const ui.Rect.fromLTWH(0, 0, 100, 100)); + final ui.Rect screenRect = const ui.Rect.fromLTWH(0, 0, 100, 100); + final RecordingCanvas recordingCanvas = RecordingCanvas(screenRect); final ui.ParagraphBuilder builder = ui.ParagraphBuilder(ui.ParagraphStyle()); builder.addText('sample'); final ui.Paragraph paragraph = builder.build(); recordingCanvas.drawParagraph(paragraph, const ui.Offset(10, 10)); + recordingCanvas.endRecording(); canvas.clear(); - recordingCanvas.apply(canvas); + recordingCanvas.apply(canvas, screenRect); }, whenDone: () { expect(mockCanvas.methodCallLog, hasLength(2)); expect(mockCanvas.methodCallLog[0].methodName, 'clear'); diff --git a/lib/web_ui/test/engine/recording_canvas_test.dart b/lib/web_ui/test/engine/recording_canvas_test.dart index 2757ba96fd4a4..5610c9c1f4de8 100644 --- a/lib/web_ui/test/engine/recording_canvas_test.dart +++ b/lib/web_ui/test/engine/recording_canvas_test.dart @@ -12,9 +12,10 @@ import '../mock_engine_canvas.dart'; void main() { RecordingCanvas underTest; MockEngineCanvas mockCanvas; + final Rect screenRect = Rect.largest; setUp(() { - underTest = RecordingCanvas(Rect.largest); + underTest = RecordingCanvas(screenRect); mockCanvas = MockEngineCanvas(); }); @@ -25,9 +26,10 @@ void main() { test('Happy case', () { underTest.drawDRRect(rrect, rrect.deflate(1), somePaint); - underTest.apply(mockCanvas); + underTest.endRecording(); + underTest.apply(mockCanvas, screenRect); - _expectDrawCall(mockCanvas, { + _expectDrawDRRectCall(mockCanvas, { 'outer': rrect, 'inner': rrect.deflate(1), 'paint': somePaint.paintData, @@ -36,7 +38,8 @@ void main() { test('Inner RRect > Outer RRect', () { underTest.drawDRRect(rrect, rrect.inflate(1), somePaint); - underTest.apply(mockCanvas); + underTest.endRecording(); + underTest.apply(mockCanvas, screenRect); // Expect nothing to be called expect(mockCanvas.methodCallLog.length, equals(1)); expect(mockCanvas.methodCallLog.single.methodName, 'endOfPaint'); @@ -45,7 +48,8 @@ void main() { test('Inner RRect not completely inside Outer RRect', () { underTest.drawDRRect( rrect, rrect.deflate(1).shift(const Offset(0.0, 10)), somePaint); - underTest.apply(mockCanvas); + underTest.endRecording(); + underTest.apply(mockCanvas, screenRect); // Expect nothing to be called expect(mockCanvas.methodCallLog.length, equals(1)); expect(mockCanvas.methodCallLog.single.methodName, 'endOfPaint'); @@ -53,7 +57,8 @@ void main() { test('Inner RRect same as Outer RRect', () { underTest.drawDRRect(rrect, rrect, somePaint); - underTest.apply(mockCanvas); + underTest.endRecording(); + underTest.apply(mockCanvas, screenRect); // Expect nothing to be called expect(mockCanvas.methodCallLog.length, equals(1)); expect(mockCanvas.methodCallLog.single.methodName, 'endOfPaint'); @@ -72,10 +77,11 @@ void main() { expect(inner.trRadius, equals(Radius.circular(-1))); underTest.drawDRRect(outer, inner, somePaint); - underTest.apply(mockCanvas); + underTest.endRecording(); + underTest.apply(mockCanvas, screenRect); // Expect to draw, even when inner has negative radii (which get ignored by canvas) - _expectDrawCall(mockCanvas, { + _expectDrawDRRectCall(mockCanvas, { 'outer': outer, 'inner': inner, 'paint': somePaint.paintData, @@ -89,19 +95,105 @@ void main() { RRect.fromRectAndCorners(const Rect.fromLTRB(12, 22, 28, 38)); underTest.drawDRRect(outer, inner, somePaint); - underTest.apply(mockCanvas); + underTest.endRecording(); + underTest.apply(mockCanvas, screenRect); - _expectDrawCall(mockCanvas, { + _expectDrawDRRectCall(mockCanvas, { 'outer': outer, 'inner': inner, 'paint': somePaint.paintData, }); }); }); + + test('Filters out paint commands outside the clip rect', () { + // Outside to the left + underTest.drawRect(Rect.fromLTWH(0.0, 20.0, 10.0, 10.0), Paint()); + + // Outside above + underTest.drawRect(Rect.fromLTWH(20.0, 0.0, 10.0, 10.0), Paint()); + + // Visible + underTest.drawRect(Rect.fromLTWH(20.0, 20.0, 10.0, 10.0), Paint()); + + // Inside the layer clip rect but zero-size + underTest.drawRect(Rect.fromLTRB(20.0, 20.0, 30.0, 20.0), Paint()); + + // Inside the layer clip but clipped out by a canvas clip + underTest.save(); + underTest.clipRect(Rect.fromLTWH(0, 0, 10, 10)); + underTest.drawRect(Rect.fromLTWH(20.0, 20.0, 10.0, 10.0), Paint()); + underTest.restore(); + + // Outside to the right + underTest.drawRect(Rect.fromLTWH(40.0, 20.0, 10.0, 10.0), Paint()); + + // Outside below + underTest.drawRect(Rect.fromLTWH(20.0, 40.0, 10.0, 10.0), Paint()); + + underTest.endRecording(); + + expect(underTest.debugPaintCommands, hasLength(10)); + final PaintDrawRect outsideLeft = underTest.debugPaintCommands[0]; + expect(outsideLeft.isClippedOut, false); + expect(outsideLeft.leftBound, 0); + expect(outsideLeft.topBound, 20); + expect(outsideLeft.rightBound, 10); + expect(outsideLeft.bottomBound, 30); + + final PaintDrawRect outsideAbove = underTest.debugPaintCommands[1]; + expect(outsideAbove.isClippedOut, false); + + final PaintDrawRect visible = underTest.debugPaintCommands[2]; + expect(visible.isClippedOut, false); + + final PaintDrawRect zeroSize = underTest.debugPaintCommands[3]; + expect(zeroSize.isClippedOut, true); + + expect(underTest.debugPaintCommands[4], isA()); + + final PaintClipRect clip = underTest.debugPaintCommands[5]; + expect(clip.isClippedOut, false); + + final PaintDrawRect clippedOut = underTest.debugPaintCommands[6]; + expect(clippedOut.isClippedOut, true); + + expect(underTest.debugPaintCommands[7], isA()); + + final PaintDrawRect outsideRight = underTest.debugPaintCommands[8]; + expect(outsideRight.isClippedOut, false); + + final PaintDrawRect outsideBelow = underTest.debugPaintCommands[9]; + expect(outsideBelow.isClippedOut, false); + + // Give it the entire screen so everything paints. + underTest.apply(mockCanvas, screenRect); + expect(mockCanvas.methodCallLog, hasLength(11)); + expect(mockCanvas.methodCallLog[0].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[1].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[2].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[3].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[4].methodName, 'save'); + expect(mockCanvas.methodCallLog[5].methodName, 'clipRect'); + expect(mockCanvas.methodCallLog[6].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[7].methodName, 'restore'); + expect(mockCanvas.methodCallLog[8].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[9].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[10].methodName, 'endOfPaint'); + + // Clip out a middle region that only contains 'drawRect' + mockCanvas.methodCallLog.clear(); + underTest.apply(mockCanvas, Rect.fromLTRB(15, 15, 35, 35)); + expect(mockCanvas.methodCallLog, hasLength(4)); + expect(mockCanvas.methodCallLog[0].methodName, 'drawRect'); + expect(mockCanvas.methodCallLog[1].methodName, 'save'); + expect(mockCanvas.methodCallLog[2].methodName, 'restore'); + expect(mockCanvas.methodCallLog[3].methodName, 'endOfPaint'); + }); } // Expect a drawDRRect call to be registered in the mock call log, with the expectedArguments -void _expectDrawCall( +void _expectDrawDRRectCall( MockEngineCanvas mock, Map expectedArguments) { expect(mock.methodCallLog.length, equals(2)); MockCanvasCall mockCall = mock.methodCallLog[0]; diff --git a/lib/web_ui/test/golden_tests/engine/canvas_blend_golden_test.dart b/lib/web_ui/test/golden_tests/engine/canvas_blend_golden_test.dart index 694274bfe516e..8407e48766b33 100644 --- a/lib/web_ui/test/golden_tests/engine/canvas_blend_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/canvas_blend_golden_test.dart @@ -23,7 +23,8 @@ void main() async { double maxDiffRatePercent = 0.0}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/canvas_clip_path_test.dart b/lib/web_ui/test/golden_tests/engine/canvas_clip_path_test.dart index 316b6b3467fde..d01620921c1d7 100644 --- a/lib/web_ui/test/golden_tests/engine/canvas_clip_path_test.dart +++ b/lib/web_ui/test/golden_tests/engine/canvas_clip_path_test.dart @@ -22,7 +22,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500)}) async { final engine.EngineCanvas engineCanvas = engine.BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/canvas_context_test.dart b/lib/web_ui/test/golden_tests/engine/canvas_context_test.dart index f0d2f15a08a77..927bf2a300fbd 100644 --- a/lib/web_ui/test/golden_tests/engine/canvas_context_test.dart +++ b/lib/web_ui/test/golden_tests/engine/canvas_context_test.dart @@ -22,7 +22,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500)}) async { final engine.EngineCanvas engineCanvas = engine.BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart b/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart index dcaf6c93b59bd..6a61f401b25bd 100644 --- a/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart @@ -26,7 +26,8 @@ void main() async { double maxDiffRatePercent = 0.0}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/canvas_reuse_test.dart b/lib/web_ui/test/golden_tests/engine/canvas_reuse_test.dart index e92f55287a252..469cc2f88faf8 100644 --- a/lib/web_ui/test/golden_tests/engine/canvas_reuse_test.dart +++ b/lib/web_ui/test/golden_tests/engine/canvas_reuse_test.dart @@ -39,7 +39,8 @@ void main() async { ..moveTo(3, 0) ..lineTo(100, 97); rc.drawPath(path, testPaint); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); engineCanvas.endOfPaint(); html.Element sceneElement = html.Element.tag('flt-scene'); @@ -69,7 +70,8 @@ void main() async { ..quadraticBezierTo(100, 0, 100, 100); rc2.drawImage(_createRealTestImage(), Offset(0, 0), Paint()); rc2.drawPath(path2, testPaint); - rc2.apply(engineCanvas); + rc2.endRecording(); + rc2.apply(engineCanvas, screenRect); sceneElement = html.Element.tag('flt-scene'); sceneElement.append(engineCanvas.rootElement); diff --git a/lib/web_ui/test/golden_tests/engine/conic_golden_test.dart b/lib/web_ui/test/golden_tests/engine/conic_golden_test.dart index 0ec9770603d40..bcf69c155e212 100644 --- a/lib/web_ui/test/golden_tests/engine/conic_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/conic_golden_test.dart @@ -31,9 +31,10 @@ void main() async { ..style = PaintingStyle.stroke; canvas.drawPath(path, paint); + canvas.endRecording(); html.document.body.append(bitmapCanvas.rootElement); - canvas.apply(bitmapCanvas); + canvas.apply(bitmapCanvas, canvasBounds); await matchGoldenFile('$scubaFileName.png', region: region); bitmapCanvas.rootElement.remove(); } diff --git a/lib/web_ui/test/golden_tests/engine/draw_vertices_golden_test.dart b/lib/web_ui/test/golden_tests/engine/draw_vertices_golden_test.dart index dc77dbc781ae8..765c614ae4cfc 100644 --- a/lib/web_ui/test/golden_tests/engine/draw_vertices_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/draw_vertices_golden_test.dart @@ -22,7 +22,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500), bool write = false}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/linear_gradient_golden_test.dart b/lib/web_ui/test/golden_tests/engine/linear_gradient_golden_test.dart index c535719597045..35b7cae8f9ecf 100644 --- a/lib/web_ui/test/golden_tests/engine/linear_gradient_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/linear_gradient_golden_test.dart @@ -21,7 +21,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500), bool write = false}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/multiline_text_clipping_golden_test.dart b/lib/web_ui/test/golden_tests/engine/multiline_text_clipping_golden_test.dart index cec631431b49d..cd3378b569896 100644 --- a/lib/web_ui/test/golden_tests/engine/multiline_text_clipping_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/multiline_text_clipping_golden_test.dart @@ -21,10 +21,11 @@ void main() async { setUpStableTestFonts(); void paintTest(EngineCanvas canvas, PaintTest painter) { - final RecordingCanvas recordingCanvas = - RecordingCanvas(const Rect.fromLTWH(0, 0, 600, 600)); + final Rect screenRect = const Rect.fromLTWH(0, 0, 600, 600); + final RecordingCanvas recordingCanvas = RecordingCanvas(screenRect); painter(recordingCanvas); - recordingCanvas.apply(canvas); + recordingCanvas.endRecording(); + recordingCanvas.apply(canvas, screenRect); } testEachCanvas( diff --git a/lib/web_ui/test/golden_tests/engine/path_metrics_test.dart b/lib/web_ui/test/golden_tests/engine/path_metrics_test.dart index 38379087867e2..b5609c72a43fd 100644 --- a/lib/web_ui/test/golden_tests/engine/path_metrics_test.dart +++ b/lib/web_ui/test/golden_tests/engine/path_metrics_test.dart @@ -25,7 +25,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500), bool write = false}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/path_to_svg_golden_test.dart b/lib/web_ui/test/golden_tests/engine/path_to_svg_golden_test.dart index c4a1d07a76e9b..bbfd9df35fc6b 100644 --- a/lib/web_ui/test/golden_tests/engine/path_to_svg_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/path_to_svg_golden_test.dart @@ -37,7 +37,8 @@ void main() async { html.document.body.append(bitmapCanvas.rootElement); html.document.body.append(svgElement); - canvas.apply(bitmapCanvas); + canvas.endRecording(); + canvas.apply(bitmapCanvas, canvasBounds); await matchGoldenFile('$scubaFileName.png', region: region); diff --git a/lib/web_ui/test/golden_tests/engine/path_transform_test.dart b/lib/web_ui/test/golden_tests/engine/path_transform_test.dart index dd53ae3153a17..342ecfd20da68 100644 --- a/lib/web_ui/test/golden_tests/engine/path_transform_test.dart +++ b/lib/web_ui/test/golden_tests/engine/path_transform_test.dart @@ -22,7 +22,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500), bool write = false}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/radial_gradient_golden_test.dart b/lib/web_ui/test/golden_tests/engine/radial_gradient_golden_test.dart index 3e40f57aa37c5..4fb58ebc3df94 100644 --- a/lib/web_ui/test/golden_tests/engine/radial_gradient_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/radial_gradient_golden_test.dart @@ -21,7 +21,8 @@ void main() async { {Rect region = const Rect.fromLTWH(0, 0, 500, 500), bool write = false}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); - rc.apply(engineCanvas); + rc.endRecording(); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); diff --git a/lib/web_ui/test/golden_tests/engine/recording_canvas_golden_test.dart b/lib/web_ui/test/golden_tests/engine/recording_canvas_golden_test.dart index c015a1ea4ec45..6b842b5267c61 100644 --- a/lib/web_ui/test/golden_tests/engine/recording_canvas_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/recording_canvas_golden_test.dart @@ -30,7 +30,7 @@ void main() async { engineCanvas ..save() ..drawRect( - rc.computePaintBounds(), + rc.pictureBounds, SurfacePaintData() ..color = const Color.fromRGBO(0, 0, 255, 1.0) ..style = PaintingStyle.stroke @@ -38,7 +38,7 @@ void main() async { ) ..restore(); - rc.apply(engineCanvas); + rc.apply(engineCanvas, screenRect); // Wrap in so that our CSS selectors kick in. final html.Element sceneElement = html.Element.tag('flt-scene'); @@ -63,15 +63,17 @@ void main() async { test('Empty canvas reports correct paint bounds', () async { final RecordingCanvas rc = RecordingCanvas(const Rect.fromLTWH(1, 2, 300, 400)); - expect(rc.computePaintBounds(), Rect.zero); + rc.endRecording(); + expect(rc.pictureBounds, Rect.zero); await _checkScreenshot(rc, 'empty_canvas'); }); test('Computes paint bounds for draw line', () async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawLine(const Offset(50, 100), const Offset(120, 140), testPaint); + rc.endRecording(); // The off by one is due to the minimum stroke width of 1. - expect(rc.computePaintBounds(), const Rect.fromLTRB(49, 99, 121, 141)); + expect(rc.pictureBounds, const Rect.fromLTRB(49, 99, 121, 141)); await _checkScreenshot(rc, 'draw_line'); }); @@ -81,8 +83,9 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawLine(const Offset(50, 100), const Offset(screenWidth + 100.0, 140), testPaint); + rc.endRecording(); // The off by one is due to the minimum stroke width of 1. - expect(rc.computePaintBounds(), + expect(rc.pictureBounds, const Rect.fromLTRB(49.0, 99.0, screenWidth, 141.0)); await _checkScreenshot(rc, 'draw_line_exceeding_limits'); }); @@ -90,7 +93,8 @@ void main() async { test('Computes paint bounds for draw rect', () async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawRect(const Rect.fromLTRB(10, 20, 30, 40), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(10, 20, 30, 40)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(10, 20, 30, 40)); await _checkScreenshot(rc, 'draw_rect'); }); @@ -100,12 +104,14 @@ void main() async { rc.drawRect( const Rect.fromLTRB(10, 20, 30 + screenWidth, 40 + screenHeight), testPaint); - expect(rc.computePaintBounds(), + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(10, 20, screenWidth, screenHeight)); rc = RecordingCanvas(screenRect); rc.drawRect(const Rect.fromLTRB(-200, -100, 30, 40), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(0, 0, 30, 40)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(0, 0, 30, 40)); await _checkScreenshot(rc, 'draw_rect_exceeding_limits'); }); @@ -113,7 +119,8 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.translate(5, 7); rc.drawRect(const Rect.fromLTRB(10, 20, 30, 40), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(15, 27, 35, 47)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(15, 27, 35, 47)); await _checkScreenshot(rc, 'translate'); }); @@ -121,7 +128,8 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.scale(2, 2); rc.drawRect(const Rect.fromLTRB(10, 20, 30, 40), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(20, 40, 60, 80)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(20, 40, 60, 80)); await _checkScreenshot(rc, 'scale'); }); @@ -130,8 +138,9 @@ void main() async { rc.rotate(math.pi / 4.0); rc.drawLine( const Offset(1, 0), Offset(50 * math.sqrt(2) - 1, 0), testPaint); + rc.endRecording(); // The extra 0.7 is due to stroke width of 1 rotated by 45 degrees. - expect(rc.computePaintBounds(), + expect(rc.pictureBounds, within(distance: 0.1, from: const Rect.fromLTRB(0, 0, 50.7, 50.7))); await _checkScreenshot(rc, 'rotate'); }); @@ -140,8 +149,9 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.skew(1.0, 0.0); rc.drawRect(const Rect.fromLTRB(20, 20, 40, 40), testPaint); + rc.endRecording(); expect( - rc.computePaintBounds(), + rc.pictureBounds, within( distance: 0.1, from: const Rect.fromLTRB(40.0, 20.0, 80.0, 40.0))); await _checkScreenshot(rc, 'skew_horizontally'); @@ -151,8 +161,9 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.skew(0.0, 1.0); rc.drawRect(const Rect.fromLTRB(20, 20, 40, 40), testPaint); + rc.endRecording(); expect( - rc.computePaintBounds(), + rc.pictureBounds, within( distance: 0.1, from: const Rect.fromLTRB(20.0, 40.0, 40.0, 80.0))); await _checkScreenshot(rc, 'skew_vertically'); @@ -180,7 +191,8 @@ void main() async { matrix[15] = 1.0; rc.transform(matrix); rc.drawRect(const Rect.fromLTRB(10, 20, 30, 40), testPaint); - expect(rc.computePaintBounds(), + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(168.0, 283.6, 224.0, 368.4)); await _checkScreenshot(rc, 'complex_transform'); }); @@ -189,7 +201,8 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawPaint(testPaint); rc.drawRect(const Rect.fromLTRB(10, 20, 30, 40), testPaint); - expect(rc.computePaintBounds(), screenRect); + rc.endRecording(); + expect(rc.pictureBounds, screenRect); await _checkScreenshot(rc, 'draw_paint'); }); @@ -199,14 +212,16 @@ void main() async { rc.drawRect(const Rect.fromLTRB(10, 20, 30, 40), testPaint); rc.drawColor(const Color(0xFFFF0000), BlendMode.multiply); rc.drawRect(const Rect.fromLTRB(10, 60, 30, 80), testPaint); - expect(rc.computePaintBounds(), screenRect); + rc.endRecording(); + expect(rc.pictureBounds, screenRect); await _checkScreenshot(rc, 'draw_color'); }); test('Computes paint bounds for draw oval', () async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawOval(const Rect.fromLTRB(10, 20, 30, 40), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(10, 20, 30, 40)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(10, 20, 30, 40)); await _checkScreenshot(rc, 'draw_oval'); }); @@ -216,7 +231,8 @@ void main() async { RRect.fromRectAndRadius( const Rect.fromLTRB(10, 20, 30, 40), const Radius.circular(5.0)), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(10, 20, 30, 40)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(10, 20, 30, 40)); await _checkScreenshot(rc, 'draw_round_rect'); }); @@ -226,7 +242,8 @@ void main() async { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawDRRect(RRect.fromRectAndCorners(const Rect.fromLTRB(10, 20, 30, 40)), RRect.fromRectAndCorners(const Rect.fromLTRB(1, 2, 3, 4)), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(0, 0, 0, 0)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(0, 0, 0, 0)); await _checkScreenshot(rc, 'draw_drrect_empty'); }); @@ -236,34 +253,44 @@ void main() async { RRect.fromRectAndCorners(const Rect.fromLTRB(10, 20, 30, 40)), RRect.fromRectAndCorners(const Rect.fromLTRB(12, 22, 28, 38)), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(10, 20, 30, 40)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(10, 20, 30, 40)); await _checkScreenshot(rc, 'draw_drrect'); }); test('Computes paint bounds for draw circle', () async { - final RecordingCanvas rc = RecordingCanvas(screenRect); + // Paint bounds of one circle. + RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawCircle(const Offset(20, 20), 10.0, testPaint); + rc.endRecording(); expect( - rc.computePaintBounds(), const Rect.fromLTRB(10.0, 10.0, 30.0, 30.0)); + rc.pictureBounds, const Rect.fromLTRB(10.0, 10.0, 30.0, 30.0)); + + // Paint bounds of a union of two circles. + rc = RecordingCanvas(screenRect); + rc.drawCircle(const Offset(20, 20), 10.0, testPaint); rc.drawCircle(const Offset(200, 300), 100.0, testPaint); + rc.endRecording(); expect( - rc.computePaintBounds(), const Rect.fromLTRB(10.0, 10.0, 300.0, 400.0)); + rc.pictureBounds, const Rect.fromLTRB(10.0, 10.0, 300.0, 400.0)); await _checkScreenshot(rc, 'draw_circle'); }); test('Computes paint bounds for draw image', () { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawImage(TestImage(), const Offset(50, 100), Paint()); + rc.endRecording(); expect( - rc.computePaintBounds(), const Rect.fromLTRB(50.0, 100.0, 70.0, 110.0)); + rc.pictureBounds, const Rect.fromLTRB(50.0, 100.0, 70.0, 110.0)); }); test('Computes paint bounds for draw image rect', () { final RecordingCanvas rc = RecordingCanvas(screenRect); rc.drawImageRect(TestImage(), const Rect.fromLTRB(1, 1, 20, 10), const Rect.fromLTRB(5, 6, 400, 500), Paint()); + rc.endRecording(); expect( - rc.computePaintBounds(), const Rect.fromLTRB(5.0, 6.0, 400.0, 500.0)); + rc.pictureBounds, const Rect.fromLTRB(5.0, 6.0, 400.0, 500.0)); }); test('Computes paint bounds for single-line draw paragraph', () async { @@ -274,8 +301,9 @@ void main() async { const double widthConstraint = 300.0; paragraph.layout(const ParagraphConstraints(width: widthConstraint)); rc.drawParagraph(paragraph, const Offset(textLeft, textTop)); + rc.endRecording(); expect( - rc.computePaintBounds(), + rc.pictureBounds, const Rect.fromLTRB(textLeft, textTop, textLeft + widthConstraint, 21.0), ); await _checkScreenshot(rc, 'draw_paragraph'); @@ -286,27 +314,35 @@ void main() async { final Paragraph paragraph = createTestParagraph(); const double textLeft = 5.0; const double textTop = 7.0; - const double widthConstraint = - 130.0; // do not go lower than the shortest word. + // Do not go lower than the shortest word. + const double widthConstraint = 130.0; paragraph.layout(const ParagraphConstraints(width: widthConstraint)); rc.drawParagraph(paragraph, const Offset(textLeft, textTop)); + rc.endRecording(); expect( - rc.computePaintBounds(), + rc.pictureBounds, const Rect.fromLTRB(textLeft, textTop, textLeft + widthConstraint, 35.0), ); await _checkScreenshot(rc, 'draw_paragraph_multi_line'); }); test('Should exclude painting outside simple clipRect', () async { - final RecordingCanvas rc = RecordingCanvas(screenRect); + // One clipped line. + RecordingCanvas rc = RecordingCanvas(screenRect); rc.clipRect(const Rect.fromLTRB(50, 50, 100, 100)); rc.drawLine(const Offset(10, 11), const Offset(20, 21), testPaint); + rc.endRecording(); + expect(rc.pictureBounds, Rect.zero); - expect(rc.computePaintBounds(), Rect.zero); + // Two clipped lines. + rc = RecordingCanvas(screenRect); + rc.clipRect(const Rect.fromLTRB(50, 50, 100, 100)); + rc.drawLine(const Offset(10, 11), const Offset(20, 21), testPaint); rc.drawLine(const Offset(52, 53), const Offset(55, 56), testPaint); + rc.endRecording(); // Extra pixel due to default line length - expect(rc.computePaintBounds(), const Rect.fromLTRB(51, 52, 56, 57)); + expect(rc.pictureBounds, const Rect.fromLTRB(51, 52, 56, 57)); await _checkScreenshot(rc, 'clip_rect_simple'); }); @@ -314,13 +350,15 @@ void main() async { RecordingCanvas rc = RecordingCanvas(screenRect); rc.clipRect(const Rect.fromLTRB(50, 50, 100, 100)); rc.drawRect(const Rect.fromLTRB(20, 60, 120, 70), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(50, 60, 100, 70)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(50, 60, 100, 70)); await _checkScreenshot(rc, 'clip_rect_intersects_paint_left_to_right'); rc = RecordingCanvas(screenRect); rc.clipRect(const Rect.fromLTRB(50, 50, 100, 100)); rc.drawRect(const Rect.fromLTRB(60, 20, 70, 200), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(60, 50, 70, 100)); + rc.endRecording(); + expect(rc.pictureBounds, const Rect.fromLTRB(60, 50, 70, 100)); await _checkScreenshot(rc, 'clip_rect_intersects_paint_top_to_bottom'); }); @@ -330,7 +368,9 @@ void main() async { rc.scale(2.0, 2.0); rc.clipRect(const Rect.fromLTRB(30, 30, 45, 45)); rc.drawRect(const Rect.fromLTRB(10, 30, 60, 35), testPaint); - expect(rc.computePaintBounds(), const Rect.fromLTRB(60, 60, 90, 70)); + rc.endRecording(); + + expect(rc.pictureBounds, const Rect.fromLTRB(60, 60, 90, 70)); await _checkScreenshot(rc, 'clip_rects_intersect'); }); @@ -340,8 +380,10 @@ void main() async { final Path path = Path(); path.addRect(const Rect.fromLTRB(20, 30, 100, 110)); rc.drawShadow(path, const Color(0xFFFF0000), 2.0, true); + rc.endRecording(); + expect( - rc.computePaintBounds(), + rc.pictureBounds, within(distance: 0.05, from: const Rect.fromLTRB(17.9, 28.5, 103.5, 114.1)), ); await _checkScreenshot(rc, 'path_with_shadow'); @@ -361,8 +403,10 @@ void main() async { ..scale(1, -1) ..clipRect(const Rect.fromLTRB(0, 0, 100, 50)) ..drawRect(const Rect.fromLTRB(0, 0, 100, 100), Paint()); + rc.endRecording(); + expect( - rc.computePaintBounds(), const Rect.fromLTRB(0.0, 50.0, 100.0, 100.0)); + rc.pictureBounds, const Rect.fromLTRB(0.0, 50.0, 100.0, 100.0)); await _checkScreenshot(rc, 'scale_negative'); }); @@ -374,8 +418,10 @@ void main() async { ..rotate(math.pi / 4.0) ..clipRect(const Rect.fromLTWH(-20, -20, 40, 40)) ..drawRect(const Rect.fromLTWH(-80, -80, 160, 160), Paint()); + rc.endRecording(); + expect( - rc.computePaintBounds(), + rc.pictureBounds, Rect.fromCircle(center: const Offset(50, 50), radius: 20 * math.sqrt(2)), ); await _checkScreenshot(rc, 'clip_rect_rotated'); @@ -388,8 +434,10 @@ void main() async { ..translate(50, 50) ..rotate(math.pi / 4.0) ..drawLine(const Offset(0, 0), const Offset(20, 20), Paint()); + rc.endRecording(); + expect( - rc.computePaintBounds(), + rc.pictureBounds, within(distance: 0.1, from: const Rect.fromLTRB(34.4, 48.6, 65.6, 79.7)), ); await _checkScreenshot(rc, 'line_rotated'); @@ -418,6 +466,7 @@ void main() async { ..style = PaintingStyle.stroke ..strokeWidth = 2.0 ..color = const Color(0xFF00FF00)); + rc.endRecording(); await _checkScreenshot(rc, 'reuse_path'); }); @@ -440,6 +489,7 @@ void main() async { ..strokeWidth = 2.0 ..color = const Color(0xFF404000)); rc.restore(); + rc.endRecording(); await _checkScreenshot(rc, 'path_with_line_and_roundrect'); }); @@ -536,7 +586,7 @@ void main() async { final SurfacePaint zeroSpreadPaint = SurfacePaint(); painter(canvas, zeroSpreadPaint); sb.addPicture(Offset.zero, recorder.endRecording()); - sb.addPicture(Offset.zero, drawBounds(canvas.computePaintBounds())); + sb.addPicture(Offset.zero, drawBounds(canvas.pictureBounds)); sb.pop(); } @@ -550,7 +600,7 @@ void main() async { ..strokeWidth = 5.0; painter(canvas, thickStrokePaint); sb.addPicture(Offset.zero, recorder.endRecording()); - sb.addPicture(Offset.zero, drawBounds(canvas.computePaintBounds())); + sb.addPicture(Offset.zero, drawBounds(canvas.pictureBounds)); sb.pop(); } @@ -563,7 +613,7 @@ void main() async { ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 5.0); painter(canvas, maskFilterBlurPaint); sb.addPicture(Offset.zero, recorder.endRecording()); - sb.addPicture(Offset.zero, drawBounds(canvas.computePaintBounds())); + sb.addPicture(Offset.zero, drawBounds(canvas.pictureBounds)); sb.pop(); } @@ -578,7 +628,7 @@ void main() async { ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 5.0); painter(canvas, thickStrokeAndBlurPaint); sb.addPicture(Offset.zero, recorder.endRecording()); - sb.addPicture(Offset.zero, drawBounds(canvas.computePaintBounds())); + sb.addPicture(Offset.zero, drawBounds(canvas.pictureBounds)); sb.pop(); } diff --git a/lib/web_ui/test/mock_engine_canvas.dart b/lib/web_ui/test/mock_engine_canvas.dart index 81f17bab46236..b0253225dc7e8 100644 --- a/lib/web_ui/test/mock_engine_canvas.dart +++ b/lib/web_ui/test/mock_engine_canvas.dart @@ -137,7 +137,10 @@ class MockEngineCanvas implements EngineCanvas { @override void drawRect(Rect rect, SurfacePaintData paint) { - _called('drawRect', arguments: paint); + _called('drawRect', arguments: { + 'rect': rect, + 'paint': paint, + }); } @override From 3882d43385026457650dd7f36270deee78f0427f Mon Sep 17 00:00:00 2001 From: Yegor Date: Tue, 14 Apr 2020 20:10:10 -0700 Subject: [PATCH 10/39] reduce web shard count from 8 to 4 (#17635) reduce web shard count from 8 to 4 by using WEB_SHARD_COUNT --- .cirrus.yml | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index c38fbb5b85941..90e36e7a0b7fa 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,9 +3,10 @@ gcp_credentials: ENCRYPTED[987a78af29b91ce8489594c9ab3fec21845bbe5ba68294b8f6def web_shard_template: &WEB_SHARD_TEMPLATE only_if: "changesInclude('.cirrus.yml', 'DEPS', 'lib/web_ui/**', 'web_sdk/**') || $CIRRUS_PR == ''" environment: - # As of March 2020, the Web shards needed 16G of RAM and 4 CPUs to run all framework tests with goldens without flaking. + # As of March 2020, the Web shards needed 16G of RAM and 4 CPUs to run all framework tests with goldens without flaking. CPU: 4 MEMORY: 16G + WEB_SHARD_COUNT: 4 compile_host_script: | cd $ENGINE_PATH/src ./flutter/tools/gn --unoptimized --full-dart-sdk @@ -124,19 +125,7 @@ task: - name: web_tests-2-linux << : *WEB_SHARD_TEMPLATE - - name: web_tests-3-linux - << : *WEB_SHARD_TEMPLATE - - - name: web_tests-4-linux - << : *WEB_SHARD_TEMPLATE - - - name: web_tests-5-linux - << : *WEB_SHARD_TEMPLATE - - - name: web_tests-6-linux - << : *WEB_SHARD_TEMPLATE - - - name: web_tests-7_last-linux # last Web shard must end with _last + - name: web_tests-3_last-linux # last Web shard must end with _last << : *WEB_SHARD_TEMPLATE - name: web_engine_analysis From 6712c3f4610fd90c5098bc2bf58981ca21811d1c Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 03:35:01 -0400 Subject: [PATCH 11/39] Roll fuchsia/sdk/core/mac-amd64 from X4B0z... to dqerH... (#17726) --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 0cf5f58a4ff9f..c052c98fb5539 100644 --- a/DEPS +++ b/DEPS @@ -538,7 +538,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': 'X4B0z1QIDjf3vCQExTtBxxMoa8LYBKAwM8OBdqk80w4C' + 'version': 'dqerHS2mu54wZhlbrLpAdKFOXrJ7aQfo1LscjfbZI3wC' } ], 'condition': 'host_os == "mac"', From adfa86d6fa263bd215f3ae7a3929084b4bd2029a Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 08:20:03 -0400 Subject: [PATCH 12/39] Roll src/third_party/skia 44e2c5f0babc..e6995c74cdfa (12 commits) (#17727) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index c052c98fb5539..245a5005881f6 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '44e2c5f0babca7ff824a65b615b4c2ac7e195470', + 'skia_revision': 'e6995c74cdfa8d083151626d571e40b023fd8fa7', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 1d54202a5146f..cec43b97d1854 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: caaa39a35d2a0fc07b167319cbd93823 +Signature: 30b7d7ca089b054d6226f254d722cb11 UNUSED LICENSES: From 7498dc2af519c1eee45a266073dcc0bc07f2a4c7 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Wed, 15 Apr 2020 07:02:58 -0700 Subject: [PATCH 13/39] Fix Windows clipboard handling (#17706) Fixes several bugs in the clipboard code, and makes some structural improvements: - Adds scoped wrappers for clipboard open/close and global lock/unlock, to prevent missing cleanup, fixing at least one case where the lock was not released. - Adds the relevant window handle to the clipboard calls, since the docs suggest that some operations won't work without one. - Adds a missing clear step to setting the clipboard data. - Switches from TEXT to UNICODETEXT to handle non-ASCII text correctly. - To enable that, adds UTF-16/-8 conversion utilities built on the Win32 APIs (rather than the deprecated std::codecvt functions, as have been previously used in the engine). - Fixes handling of getting data when the clipboard is empty, correctly returning null. - Passes more errors back through the method channel, with details, for easier debugging of future issues. Fixes https://github.com/flutter/flutter/issues/54226 --- ci/licenses_golden/licenses_flutter | 3 + shell/platform/windows/BUILD.gn | 3 + shell/platform/windows/platform_handler.cc | 269 ++++++++++++++---- shell/platform/windows/platform_handler.h | 3 - shell/platform/windows/string_conversion.cc | 55 ++++ shell/platform/windows/string_conversion.h | 22 ++ .../windows/string_conversion_unittests.cc | 37 +++ 7 files changed, 336 insertions(+), 56 deletions(-) create mode 100644 shell/platform/windows/string_conversion.cc create mode 100644 shell/platform/windows/string_conversion.h create mode 100644 shell/platform/windows/string_conversion_unittests.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index efcc72ebf43e9..7340ce6a04007 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1182,6 +1182,9 @@ FILE: ../../../flutter/shell/platform/windows/keyboard_hook_handler.h FILE: ../../../flutter/shell/platform/windows/platform_handler.cc FILE: ../../../flutter/shell/platform/windows/platform_handler.h FILE: ../../../flutter/shell/platform/windows/public/flutter_windows.h +FILE: ../../../flutter/shell/platform/windows/string_conversion.cc +FILE: ../../../flutter/shell/platform/windows/string_conversion.h +FILE: ../../../flutter/shell/platform/windows/string_conversion_unittests.cc FILE: ../../../flutter/shell/platform/windows/text_input_plugin.cc FILE: ../../../flutter/shell/platform/windows/text_input_plugin.h FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.cc diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index 5de1a712a482e..ce8c6c0ec7fe1 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -49,6 +49,8 @@ source_set("flutter_windows_source") { "keyboard_hook_handler.h", "platform_handler.cc", "platform_handler.h", + "string_conversion.cc", + "string_conversion.h", "text_input_plugin.cc", "text_input_plugin.h", "win32_flutter_window.cc", @@ -108,6 +110,7 @@ executable("flutter_windows_unittests") { sources = [ "dpi_utils_unittests.cc", + "string_conversion_unittests.cc", "testing/win32_flutter_window_test.cc", "testing/win32_flutter_window_test.h", "testing/win32_window_test.cc", diff --git a/shell/platform/windows/platform_handler.cc b/shell/platform/windows/platform_handler.cc index f1540a9819016..c4b83130a785b 100644 --- a/shell/platform/windows/platform_handler.cc +++ b/shell/platform/windows/platform_handler.cc @@ -7,8 +7,11 @@ #include #include +#include #include "flutter/shell/platform/common/cpp/json_method_codec.h" +#include "flutter/shell/platform/windows/string_conversion.h" +#include "flutter/shell/platform/windows/win32_flutter_window.h" static constexpr char kChannelName[] = "flutter/platform"; @@ -18,11 +21,182 @@ static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData"; static constexpr char kTextPlainFormat[] = "text/plain"; static constexpr char kTextKey[] = "text"; -static constexpr char kUnknownClipboardFormatError[] = - "Unknown clipboard format error"; +static constexpr char kClipboardError[] = "Clipboard error"; +static constexpr char kUnknownClipboardFormatMessage[] = + "Unknown clipboard format"; namespace flutter { +namespace { + +// A scoped wrapper for GlobalAlloc/GlobalFree. +class ScopedGlobalMemory { + public: + // Allocates |bytes| bytes of global memory with the given flags. + ScopedGlobalMemory(unsigned int flags, size_t bytes) { + memory_ = ::GlobalAlloc(flags, bytes); + if (!memory_) { + std::cerr << "Unable to allocate global memory: " << ::GetLastError(); + } + } + + ~ScopedGlobalMemory() { + if (memory_) { + if (::GlobalFree(memory_) != nullptr) { + std::cerr << "Failed to free global allocation: " << ::GetLastError(); + } + } + } + + // Prevent copying. + ScopedGlobalMemory(ScopedGlobalMemory const&) = delete; + ScopedGlobalMemory& operator=(ScopedGlobalMemory const&) = delete; + + // Returns the memory pointer, which will be nullptr if allocation failed. + void* get() { return memory_; } + + void* release() { + void* memory = memory_; + memory_ = nullptr; + return memory; + } + + private: + HGLOBAL memory_; +}; + +// A scoped wrapper for GlobalLock/GlobalUnlock. +class ScopedGlobalLock { + public: + // Attempts to acquire a global lock on |memory| for the life of this object. + ScopedGlobalLock(HGLOBAL memory) { + source_ = memory; + if (memory) { + locked_memory_ = ::GlobalLock(memory); + if (!locked_memory_) { + std::cerr << "Unable to acquire global lock: " << ::GetLastError(); + } + } + } + + ~ScopedGlobalLock() { + if (locked_memory_) { + if (!::GlobalUnlock(source_)) { + DWORD error = ::GetLastError(); + if (error != NO_ERROR) { + std::cerr << "Unable to release global lock: " << ::GetLastError(); + } + } + } + } + + // Prevent copying. + ScopedGlobalLock(ScopedGlobalLock const&) = delete; + ScopedGlobalLock& operator=(ScopedGlobalLock const&) = delete; + + // Returns the locked memory pointer, which will be nullptr if acquiring the + // lock failed. + void* get() { return locked_memory_; } + + private: + HGLOBAL source_; + void* locked_memory_; +}; + +// A Clipboard wrapper that automatically closes the clipboard when it goes out +// of scope. +class ScopedClipboard { + public: + ScopedClipboard(); + ~ScopedClipboard(); + + // Prevent copying. + ScopedClipboard(ScopedClipboard const&) = delete; + ScopedClipboard& operator=(ScopedClipboard const&) = delete; + + // Attempts to open the clipboard for the given window, returning true if + // successful. + bool Open(HWND window); + + // Returns true if there is string data available to get. + bool HasString(); + + // Returns string data from the clipboard. + // + // If getting a string fails, returns no value. Get error information with + // ::GetLastError(). + // + // Open(...) must have succeeded to call this method. + std::optional GetString(); + + // Sets the string content of the clipboard, returning true on success. + // + // On failure, get error information with ::GetLastError(). + // + // Open(...) must have succeeded to call this method. + bool SetString(const std::wstring string); + + private: + bool opened_ = false; +}; + +ScopedClipboard::ScopedClipboard() {} + +ScopedClipboard::~ScopedClipboard() { + if (opened_) { + ::CloseClipboard(); + } +} + +bool ScopedClipboard::Open(HWND window) { + opened_ = ::OpenClipboard(window); + return opened_; +} + +bool ScopedClipboard::HasString() { + // Allow either plain text format, since getting data will auto-interpolate. + return ::IsClipboardFormatAvailable(CF_UNICODETEXT) || + ::IsClipboardFormatAvailable(CF_TEXT); +} + +std::optional ScopedClipboard::GetString() { + assert(opened_); + + HANDLE data = ::GetClipboardData(CF_UNICODETEXT); + if (data == nullptr) { + return std::nullopt; + } + ScopedGlobalLock locked_data(data); + if (!locked_data.get()) { + return std::nullopt; + } + return std::optional(static_cast(locked_data.get())); +} + +bool ScopedClipboard::SetString(const std::wstring string) { + assert(opened_); + if (!::EmptyClipboard()) { + return false; + } + size_t null_terminated_byte_count = + sizeof(decltype(string)::traits_type::char_type) * (string.size() + 1); + ScopedGlobalMemory destination_memory(GMEM_MOVEABLE, + null_terminated_byte_count); + ScopedGlobalLock locked_memory(destination_memory.get()); + if (!locked_memory.get()) { + return false; + } + memcpy(locked_memory.get(), string.c_str(), null_terminated_byte_count); + if (!::SetClipboardData(CF_UNICODETEXT, locked_memory.get())) { + return false; + } + // The clipboard now owns the global memory. + destination_memory.release(); + return true; +} + +} // namespace + PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, Win32FlutterWindow* window) : channel_(std::make_unique>( @@ -47,76 +221,65 @@ void PlatformHandler::HandleMethodCall( const rapidjson::Value& format = method_call.arguments()[0]; if (strcmp(format.GetString(), kTextPlainFormat) != 0) { - result->Error(kUnknownClipboardFormatError, - "Windows clipboard API only supports text."); + result->Error(kClipboardError, kUnknownClipboardFormatMessage); return; } - auto clipboardData = GetClipboardString(); - - if (clipboardData.empty()) { - result->Error(kUnknownClipboardFormatError, - "Failed to retrieve clipboard data from win32 api."); + ScopedClipboard clipboard; + if (!clipboard.Open(window_->GetWindowHandle())) { + rapidjson::Document error_code; + error_code.SetInt(::GetLastError()); + result->Error(kClipboardError, "Unable to open clipboard", &error_code); return; } + if (!clipboard.HasString()) { + rapidjson::Document null; + result->Success(&null); + return; + } + std::optional clipboard_string = clipboard.GetString(); + if (!clipboard_string) { + rapidjson::Document error_code; + error_code.SetInt(::GetLastError()); + result->Error(kClipboardError, "Unable to get clipboard data", + &error_code); + return; + } + rapidjson::Document document; document.SetObject(); rapidjson::Document::AllocatorType& allocator = document.GetAllocator(); - document.AddMember(rapidjson::Value(kTextKey, allocator), - rapidjson::Value(clipboardData, allocator), allocator); + document.AddMember( + rapidjson::Value(kTextKey, allocator), + rapidjson::Value(Utf8FromUtf16(*clipboard_string), allocator), + allocator); result->Success(&document); - } else if (method.compare(kSetClipboardDataMethod) == 0) { const rapidjson::Value& document = *method_call.arguments(); rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey); if (itr == document.MemberEnd()) { - result->Error(kUnknownClipboardFormatError, - "Missing text to store on clipboard."); + result->Error(kClipboardError, kUnknownClipboardFormatMessage); + return; + } + + ScopedClipboard clipboard; + if (!clipboard.Open(window_->GetWindowHandle())) { + rapidjson::Document error_code; + error_code.SetInt(::GetLastError()); + result->Error(kClipboardError, "Unable to open clipboard", &error_code); + return; + } + if (!clipboard.SetString(Utf16FromUtf8(itr->value.GetString()))) { + rapidjson::Document error_code; + error_code.SetInt(::GetLastError()); + result->Error(kClipboardError, "Unable to set clipboard data", + &error_code); return; } - SetClipboardString(std::string(itr->value.GetString())); result->Success(); } else { result->NotImplemented(); } } -std::string PlatformHandler::GetClipboardString() { - if (!OpenClipboard(nullptr)) { - return nullptr; - } - - HANDLE data = GetClipboardData(CF_TEXT); - if (data == nullptr) { - CloseClipboard(); - return nullptr; - } - - const char* clipboardData = static_cast(GlobalLock(data)); - - if (clipboardData == nullptr) { - CloseClipboard(); - return nullptr; - } - - auto result = std::string(clipboardData); - GlobalUnlock(data); - CloseClipboard(); - return result; -} - -void PlatformHandler::SetClipboardString(std::string data) { - if (!OpenClipboard(nullptr)) { - return; - } - - auto htext = GlobalAlloc(GMEM_MOVEABLE, data.size()); - - memcpy(GlobalLock(htext), data.c_str(), data.size()); - - SetClipboardData(CF_TEXT, htext); - - CloseClipboard(); -} - } // namespace flutter diff --git a/shell/platform/windows/platform_handler.h b/shell/platform/windows/platform_handler.h index 58fbf55031c87..8cb09a80666a7 100644 --- a/shell/platform/windows/platform_handler.h +++ b/shell/platform/windows/platform_handler.h @@ -29,9 +29,6 @@ class PlatformHandler { // The MethodChannel used for communication with the Flutter engine. std::unique_ptr> channel_; - static std::string GetClipboardString(); - static void SetClipboardString(std::string data); - // A reference to the win32 window. Win32FlutterWindow* window_; }; diff --git a/shell/platform/windows/string_conversion.cc b/shell/platform/windows/string_conversion.cc new file mode 100644 index 0000000000000..1519337a0acba --- /dev/null +++ b/shell/platform/windows/string_conversion.cc @@ -0,0 +1,55 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/windows/string_conversion.h" + +#include + +namespace flutter { + +std::string Utf8FromUtf16(const std::wstring& utf16_string) { + if (utf16_string.empty()) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), + static_cast(utf16_string.length()), nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), + static_cast(utf16_string.length()), utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} + +std::wstring Utf16FromUtf8(const std::string& utf8_string) { + if (utf8_string.empty()) { + return std::wstring(); + } + int target_length = + ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(), + static_cast(utf8_string.length()), nullptr, 0); + if (target_length == 0) { + return std::wstring(); + } + std::wstring utf16_string; + utf16_string.resize(target_length); + int converted_length = + ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(), + static_cast(utf8_string.length()), + utf16_string.data(), target_length); + if (converted_length == 0) { + return std::wstring(); + } + return utf16_string; +} + +} // namespace flutter diff --git a/shell/platform/windows/string_conversion.h b/shell/platform/windows/string_conversion.h new file mode 100644 index 0000000000000..ce84be2f46f85 --- /dev/null +++ b/shell/platform/windows/string_conversion.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_STRING_CONVERSION_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_STRING_CONVERSION_H_ + +#include + +namespace flutter { + +// Converts a string from UTF-16 to UTF-8. Returns an empty string if the +// input is not valid UTF-16. +std::string Utf8FromUtf16(const std::wstring& utf16_string); + +// Converts a string from UTF-8 to UTF-16. Returns an empty string if the +// input is not valid UTF-8. +std::wstring Utf16FromUtf8(const std::string& utf8_string); + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_STRING_CONVERSION_H_ diff --git a/shell/platform/windows/string_conversion_unittests.cc b/shell/platform/windows/string_conversion_unittests.cc new file mode 100644 index 0000000000000..aa8dc967f3c81 --- /dev/null +++ b/shell/platform/windows/string_conversion_unittests.cc @@ -0,0 +1,37 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/windows/string_conversion.h" + +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +TEST(StringConversion, Utf16FromUtf8Empty) { + EXPECT_EQ(Utf16FromUtf8(""), L""); +} + +TEST(StringConversion, Utf16FromUtf8Ascii) { + EXPECT_EQ(Utf16FromUtf8("abc123"), L"abc123"); +} + +TEST(StringConversion, Utf16FromUtf8Unicode) { + EXPECT_EQ(Utf16FromUtf8("\xe2\x98\x83"), L"\x2603"); +} + +TEST(StringConversion, Utf8FromUtf16Empty) { + EXPECT_EQ(Utf8FromUtf16(L""), ""); +} + +TEST(StringConversion, Utf8FromUtf16Ascii) { + EXPECT_EQ(Utf8FromUtf16(L"abc123"), "abc123"); +} + +TEST(StringConversion, Utf8FromUtf16Unicode) { + EXPECT_EQ(Utf8FromUtf16(L"\x2603"), "\xe2\x98\x83"); +} + +} // namespace testing +} // namespace flutter From 175a00533def937599b35bcc600f5eecc13fd09e Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 11:25:02 -0400 Subject: [PATCH 14/39] Roll src/third_party/skia e6995c74cdfa..d276e3f0099a (2 commits) (#17730) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 245a5005881f6..8511f2d3e8967 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': 'e6995c74cdfa8d083151626d571e40b023fd8fa7', + 'skia_revision': 'd276e3f0099ae0e257d83927048ec5f64d6fcb54', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index cec43b97d1854..defdb9cd161c7 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 30b7d7ca089b054d6226f254d722cb11 +Signature: cc0f7725d7331471c5175ccc656ebf94 UNUSED LICENSES: From e076a964f83e86549a37201651895efe0443d016 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 12:10:02 -0400 Subject: [PATCH 15/39] Roll src/third_party/dart 3e43a3dcadf9..eb18db2116dc (37 commits) (#17731) --- DEPS | 4 ++-- ci/licenses_golden/licenses_third_party | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DEPS b/DEPS index 8511f2d3e8967..153105f2abf7c 100644 --- a/DEPS +++ b/DEPS @@ -34,7 +34,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS. # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '3e43a3dcadf96c0f1e30b12e0a1805df5a336c3c', + 'dart_revision': 'eb18db2116dc2fd40733eee8c1d2018117ad6621', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py @@ -62,7 +62,7 @@ vars = { 'dart_http_throttle_tag': '1.0.2', 'dart_intl_tag': '0.16.1', 'dart_json_rpc_2_tag': '2.0.9', - 'dart_linter_tag': '0.1.115', + 'dart_linter_tag': '0.1.114', 'dart_logging_tag': '0.11.3+2', 'dart_markdown_tag': '2.1.1', 'dart_matcher_tag': '0.12.5', diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index 18cdd40a7c8e2..d124ee0503a9e 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: cdaa56a5f77c8a504af3e424af40fb9f +Signature: 19b95bda7596af5cc853d0d10e2aaf54 UNUSED LICENSES: From 9afc6faaa39e34b33e8c21afc6679c315be3b2d6 Mon Sep 17 00:00:00 2001 From: Vyacheslav Egorov Date: Wed, 15 Apr 2020 19:35:04 +0200 Subject: [PATCH 16/39] Release acquired typed data before calling Dart_SetReturnValue. (#17729) --- third_party/tonic/typed_data/typed_list.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/third_party/tonic/typed_data/typed_list.cc b/third_party/tonic/typed_data/typed_list.cc index 3a491c005ec85..ffe662591dea4 100644 --- a/third_party/tonic/typed_data/typed_list.cc +++ b/third_party/tonic/typed_data/typed_list.cc @@ -69,7 +69,9 @@ template void DartConverter>::SetReturnValue( Dart_NativeArguments args, TypedList val) { - Dart_SetReturnValue(args, val.dart_handle()); + Dart_Handle result = val.dart_handle(); + val.Release(); // Must release acquired typed data before calling Dart API. + Dart_SetReturnValue(args, result); } template From 9a9ed6386f765a7ecddab498efd33db7fa73bce0 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 14:25:01 -0400 Subject: [PATCH 17/39] Roll src/third_party/skia d276e3f0099a..9ff1d841f6cc (4 commits) (#17733) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 153105f2abf7c..8b608dc71e831 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': 'd276e3f0099ae0e257d83927048ec5f64d6fcb54', + 'skia_revision': '9ff1d841f6cce901531bfba06e4ca79c50d8a696', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index defdb9cd161c7..ba4f06e609a17 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: cc0f7725d7331471c5175ccc656ebf94 +Signature: e1d2321667cc377404bf969087467bb9 UNUSED LICENSES: From 3791f0bc8c0809bfe6150f611c5cf82c3541beeb Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Wed, 15 Apr 2020 11:52:52 -0700 Subject: [PATCH 18/39] Added some tests after the fact for #17499 (#17714) --- .../framework/Source/SemanticsObjectTest.mm | 26 +++++++++++++++++++ .../ios/IosUnitTests/build_and_run_tests.sh | 2 ++ 2 files changed, 28 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm index 8ec62338ab825..21bd5611beee1 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm @@ -38,4 +38,30 @@ - (void)testCreate { XCTAssertNotNil(object); } +- (void)testSetChildren { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + SemanticsObject* parent = [[SemanticsObject alloc] initWithBridge:bridge uid:0]; + SemanticsObject* child = [[SemanticsObject alloc] initWithBridge:bridge uid:1]; + parent.children = @[ child ]; + XCTAssertEqual(parent, child.parent); + parent.children = @[]; + XCTAssertNil(child.parent); +} + +- (void)testReplaceChildAtIndex { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + SemanticsObject* parent = [[SemanticsObject alloc] initWithBridge:bridge uid:0]; + SemanticsObject* child1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1]; + SemanticsObject* child2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2]; + parent.children = @[ child1 ]; + [parent replaceChildAtIndex:0 withChild:child2]; + XCTAssertNil(child1.parent); + XCTAssertEqual(parent, child2.parent); + XCTAssertEqualObjects(parent.children, @[ child2 ]); +} + @end diff --git a/testing/ios/IosUnitTests/build_and_run_tests.sh b/testing/ios/IosUnitTests/build_and_run_tests.sh index 0c586192d9490..833459c019d45 100755 --- a/testing/ios/IosUnitTests/build_and_run_tests.sh +++ b/testing/ios/IosUnitTests/build_and_run_tests.sh @@ -1,5 +1,7 @@ #!/bin/sh +set -e + FLUTTER_ENGINE=ios_debug_sim_unopt if [ $# -eq 1 ]; then From 98412a7adcda452446deeed9987021a95b313e6b Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 17:00:02 -0400 Subject: [PATCH 19/39] Roll fuchsia/sdk/core/linux-amd64 from M1a9q... to Udupa... (#17732) --- DEPS | 2 +- ci/licenses_golden/licenses_fuchsia | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/DEPS b/DEPS index 8b608dc71e831..1a8e881b134a2 100644 --- a/DEPS +++ b/DEPS @@ -558,7 +558,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'M1a9qkxiTlatk7o1E8lede6K7dr5fnTSKcoGqW2SsBUC' + 'version': 'Udupac5RMB5ivSEokSjG2BTEtxphge9ZlfTuALVW8PYC' } ], 'condition': 'host_os == "linux"', diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index 7077ded728113..e91ed62e7ab67 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: 8b13b3b022828174f91e229cf515afa5 +Signature: 2da6a5acd07c2b9887c4985c26a2708d UNUSED LICENSES: @@ -2674,7 +2674,6 @@ FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.media/stream_processor.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.media/stream_type.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.media/timeline_function.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.mediacodec/codec_factory.fidl -FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.modular/intent/intent_handler.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.modular/module/module_manifest.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.modular/story/puppet_master.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.modular/story/story_command.fidl From 2fe73589fb67334e5f57464a23ceccfd222e60ce Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Wed, 15 Apr 2020 14:33:00 -0700 Subject: [PATCH 20/39] Use the right constant for macOS event timestamps (#17713) The NSEvent->Flutter event conversion code for pointer events was multiplying seconds by nanoseconds per milliseconds. While this does end up giving the right number of microseconds, it's a very confusing way to write it. --- .../darwin/macos/framework/Source/FlutterViewController.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index e9c26be8e0b32..4813ab8fe2279 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -405,7 +405,7 @@ - (void)dispatchMouseEvent:(NSEvent*)event phase:(FlutterPointerPhase)phase { FlutterPointerEvent flutterEvent = { .struct_size = sizeof(flutterEvent), .phase = phase, - .timestamp = static_cast(event.timestamp * NSEC_PER_MSEC), + .timestamp = static_cast(event.timestamp * USEC_PER_SEC), .x = locationInBackingCoordinates.x, .y = -locationInBackingCoordinates.y, // convertPointToBacking makes this negative. .device_kind = kFlutterPointerDeviceKindMouse, From 4151d8ed9b5355b888fb8e853d45d569de664b99 Mon Sep 17 00:00:00 2001 From: godofredoc <54371434+godofredoc@users.noreply.github.com> Date: Wed, 15 Apr 2020 14:58:44 -0700 Subject: [PATCH 21/39] Remove fuchsia build from cirrus. (#17736) Building fuchsia is covered already by LUCI. Link to luci execution: https://ci.chromium.org/p/flutter/builders/try/Linux%20Fuchsia Bug: https://github.com/flutter/flutter/issues/54412 --- .cirrus.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 90e36e7a0b7fa..447d02fc70dac 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -196,8 +196,3 @@ task: build_script: | cd $ENGINE_PATH/src/flutter ./ci/build.sh - - name: build_fuchsia_artifacts - compile_fuchsia_script: | - cd $ENGINE_PATH/src - ./flutter/tools/fuchsia/build_fuchsia_artifacts.py --engine-version HEAD --runtime-mode debug --no-lto --archs x64 - cd $ENGINE_PATH/src/flutter From fe45c73cb50bfc9bd26edb0a3d8af568d3ddb665 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 18:20:02 -0400 Subject: [PATCH 22/39] Roll src/third_party/dart eb18db2116dc..d5c38cd35486 (18 commits) (#17739) --- DEPS | 4 ++-- ci/licenses_golden/licenses_third_party | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DEPS b/DEPS index 1a8e881b134a2..cce0089e8c473 100644 --- a/DEPS +++ b/DEPS @@ -34,7 +34,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS. # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'eb18db2116dc2fd40733eee8c1d2018117ad6621', + 'dart_revision': 'd5c38cd35486bbe6f7c77a9c013db6eb82683a23', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py @@ -72,7 +72,7 @@ vars = { 'dart_oauth2_tag': '1.2.1', 'dart_observatory_pub_packages_rev': '0894122173b0f98eb08863a7712e78407d4477bc', 'dart_package_config_tag': 'v1.9.2', - 'dart_path_tag': '1.6.2', + 'dart_path_tag': '1.7.0', 'dart_pedantic_tag': 'v1.9.0', 'dart_pool_tag': '1.3.6', 'dart_protobuf_rev': '3746c8fd3f2b0147623a8e3db89c3ff4330de760', diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index d124ee0503a9e..e3e8741eb8c29 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: 19b95bda7596af5cc853d0d10e2aaf54 +Signature: 3f705f1fbf9d8aa782e8b233788ff513 UNUSED LICENSES: From f9c478d47dbc07dab89fbd6fcbc468ea8b74fbf8 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Wed, 15 Apr 2020 19:00:02 -0400 Subject: [PATCH 23/39] Roll fuchsia/sdk/core/mac-amd64 from dqerH... to urCsS... (#17741) --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index cce0089e8c473..4da05e532ca53 100644 --- a/DEPS +++ b/DEPS @@ -538,7 +538,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': 'dqerHS2mu54wZhlbrLpAdKFOXrJ7aQfo1LscjfbZI3wC' + 'version': 'urCsSKhz2Ls7vT55uPrHLoQFUHR9DyW0bgivrJmnwmcC' } ], 'condition': 'host_os == "mac"', From fd971d4c480cda14f62cf696d88585b68e3058ad Mon Sep 17 00:00:00 2001 From: Francisco Magdaleno Date: Thu, 16 Apr 2020 00:52:43 +0000 Subject: [PATCH 24/39] Remove franciscojma86 from autoassign (#17717) --- .github/auto_assign.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml index 638c686bd5cdc..2c9c96cbe1a1c 100644 --- a/.github/auto_assign.yml +++ b/.github/auto_assign.yml @@ -17,7 +17,6 @@ reviewers: - GaryQian - jason-simmons - iskakaushik - - franciscojma86 - cbracken - flar From 6e1d7f888354a884d2defe2df8c331af204b5214 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 15 Apr 2020 19:07:12 -0700 Subject: [PATCH 25/39] [a11y] Support TalkBack reading by word, character, and paragraph (#17626) --- shell/platform/android/BUILD.gn | 1 + .../io/flutter/view/AccessibilityBridge.java | 15 +- .../platform/android/platform_view_android.cc | 8 + .../test/io/flutter/FlutterTestSuite.java | 2 + .../flutter/view/AccessibilityBridgeTest.java | 188 ++++++++++++++++++ 5 files changed, 206 insertions(+), 8 deletions(-) create mode 100644 shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 57992c62961c2..cc5d0f8b59713 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -446,6 +446,7 @@ action("robolectric_tests") { "test/io/flutter/plugins/GeneratedPluginRegistrant.java", "test/io/flutter/util/FakeKeyEvent.java", "test/io/flutter/util/PreconditionsTest.java", + "test/io/flutter/view/AccessibilityBridgeTest.java", ] outputs = [ diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index 4d4fe46a33281..bd01f405ab213 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -739,6 +739,12 @@ && shouldSetCollectionInfo(semanticsNode)) { result.setLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE); } + if (semanticsNode.hasFlag(Flag.IS_TEXT_FIELD)) { + result.setText(semanticsNode.getValueLabelHint()); + } else if (!semanticsNode.hasFlag(Flag.SCOPES_ROUTE)) { + result.setContentDescription(semanticsNode.getValueLabelHint()); + } + boolean hasCheckedState = semanticsNode.hasFlag(Flag.HAS_CHECKED_STATE); boolean hasToggledState = semanticsNode.hasFlag(Flag.HAS_TOGGLED_STATE); if (BuildConfig.DEBUG && (hasCheckedState && hasToggledState)) { @@ -747,7 +753,6 @@ && shouldSetCollectionInfo(semanticsNode)) { result.setCheckable(hasCheckedState || hasToggledState); if (hasCheckedState) { result.setChecked(semanticsNode.hasFlag(Flag.IS_CHECKED)); - result.setContentDescription(semanticsNode.getValueLabelHint()); if (semanticsNode.hasFlag(Flag.IS_IN_MUTUALLY_EXCLUSIVE_GROUP)) { result.setClassName("android.widget.RadioButton"); } else { @@ -756,13 +761,7 @@ && shouldSetCollectionInfo(semanticsNode)) { } else if (hasToggledState) { result.setChecked(semanticsNode.hasFlag(Flag.IS_TOGGLED)); result.setClassName("android.widget.Switch"); - result.setContentDescription(semanticsNode.getValueLabelHint()); - } else if (!semanticsNode.hasFlag(Flag.SCOPES_ROUTE)) { - // Setting the text directly instead of the content description - // will replace the "checked" or "not-checked" label. - result.setText(semanticsNode.getValueLabelHint()); } - result.setSelected(semanticsNode.hasFlag(Flag.IS_SELECTED)); // Heading support @@ -1660,7 +1659,7 @@ public enum Action { // Must match SemanticsFlag in semantics.dart // https://github.com/flutter/engine/blob/master/lib/ui/semantics.dart - private enum Flag { + /* Package */ enum Flag { HAS_CHECKED_STATE(1 << 0), IS_CHECKED(1 << 1), IS_SELECTED(1 << 2), diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index a58efec690e37..d5e53d4f1bf42 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -247,6 +247,14 @@ void PlatformViewAndroid::UpdateSemantics( value.second.customAccessibilityActions.size() * kBytesPerChild; } + // The encoding defined here is used in: + // + // * AccessibilityBridge.java + // * AccessibilityBridgeTest.java + // * accessibility_bridge.mm + // + // If any of the encoding structure or length is changed, those locations + // must be updated (at a minimum). std::vector buffer(num_bytes); int32_t* buffer_int32 = reinterpret_cast(&buffer[0]); float* buffer_float32 = reinterpret_cast(&buffer[0]); diff --git a/shell/platform/android/test/io/flutter/FlutterTestSuite.java b/shell/platform/android/test/io/flutter/FlutterTestSuite.java index d793f5a731877..509c91c298988 100644 --- a/shell/platform/android/test/io/flutter/FlutterTestSuite.java +++ b/shell/platform/android/test/io/flutter/FlutterTestSuite.java @@ -22,6 +22,7 @@ import io.flutter.plugin.platform.PlatformPluginTest; import io.flutter.plugin.platform.SingleViewPresentationTest; import io.flutter.util.PreconditionsTest; +import io.flutter.view.AccessibilityBridgeTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -55,6 +56,7 @@ SingleViewPresentationTest.class, SmokeTest.class, TextInputPluginTest.class, + AccessibilityBridgeTest.class, }) /** Runs all of the unit tests listed in the {@code @SuiteClasses} annotation. */ public class FlutterTestSuite {} diff --git a/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java b/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java new file mode 100644 index 0000000000000..aef458733d7b7 --- /dev/null +++ b/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java @@ -0,0 +1,188 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.view; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.view.View; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import io.flutter.embedding.engine.systemchannels.AccessibilityChannel; +import io.flutter.plugin.platform.PlatformViewsAccessibilityDelegate; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@Config(manifest = Config.NONE) +@RunWith(RobolectricTestRunner.class) +public class AccessibilityBridgeTest { + + @Test + public void itDescribesNonTextFieldsWithAContentDescription() { + AccessibilityBridge accessibilityBridge = setUpBridge(); + + TestSemanticsNode testSemanticsNode = new TestSemanticsNode(); + testSemanticsNode.label = "Hello, World"; + TestSemanticsUpdate testSemanticsUpdate = testSemanticsNode.toUpdate(); + + accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings); + AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0); + + assertEquals(nodeInfo.getContentDescription(), "Hello, World"); + assertEquals(nodeInfo.getText(), null); + } + + @Test + public void itDescribesTextFieldsWithText() { + AccessibilityBridge accessibilityBridge = setUpBridge(); + + TestSemanticsNode testSemanticsNode = new TestSemanticsNode(); + testSemanticsNode.label = "Hello, World"; + testSemanticsNode.addFlag(AccessibilityBridge.Flag.IS_TEXT_FIELD); + TestSemanticsUpdate testSemanticsUpdate = testSemanticsNode.toUpdate(); + + accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings); + AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0); + + assertEquals(nodeInfo.getContentDescription(), null); + assertEquals(nodeInfo.getText(), "Hello, World"); + } + + @Test + public void itDoesNotContainADescriptionIfScopesRoute() { + AccessibilityBridge accessibilityBridge = setUpBridge(); + + TestSemanticsNode testSemanticsNode = new TestSemanticsNode(); + testSemanticsNode.label = "Hello, World"; + testSemanticsNode.addFlag(AccessibilityBridge.Flag.SCOPES_ROUTE); + TestSemanticsUpdate testSemanticsUpdate = testSemanticsNode.toUpdate(); + + accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings); + AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0); + + assertEquals(nodeInfo.getContentDescription(), null); + assertEquals(nodeInfo.getText(), null); + } + + AccessibilityBridge setUpBridge() { + View view = mock(View.class); + Context context = mock(Context.class); + when(view.getContext()).thenReturn(context); + when(context.getPackageName()).thenReturn("test"); + AccessibilityChannel accessibilityChannel = mock(AccessibilityChannel.class); + AccessibilityManager accessibilityManager = mock(AccessibilityManager.class); + ContentResolver contentResolver = mock(ContentResolver.class); + PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate = + mock(PlatformViewsAccessibilityDelegate.class); + AccessibilityBridge accessibilityBridge = + new AccessibilityBridge( + view, + accessibilityChannel, + accessibilityManager, + contentResolver, + platformViewsAccessibilityDelegate); + return accessibilityBridge; + } + + /// The encoding for semantics is described in platform_view_android.cc + class TestSemanticsUpdate { + TestSemanticsUpdate(ByteBuffer buffer, String[] strings) { + this.buffer = buffer; + this.strings = strings; + } + + final ByteBuffer buffer; + final String[] strings; + } + + class TestSemanticsNode { + TestSemanticsNode() {} + + void addFlag(AccessibilityBridge.Flag flag) { + flags |= flag.value; + } + + // These fields are declared in the order they should be + // encoded. + int id = 0; + int flags = 0; + int actions = 0; + int maxValueLength = 0; + int currentValueLength = 0; + int textSelectionBase = 0; + int textSelectionExtent = 0; + int platformViewId = -1; + int scrollChildren = 0; + int scrollIndex = 0; + float scrollPosition = 0.0f; + float scrollExtentMax = 0.0f; + float scrollExtentMin = 0.0f; + String label = null; + String value = null; + String increasedValue = null; + String decreasedValue = null; + String hint = null; + int textDirection = 0; + float left = 0.0f; + float top = 0.0f; + float right = 0.0f; + float bottom = 0.0f; + // children and custom actions not supported. + + TestSemanticsUpdate toUpdate() { + ArrayList strings = new ArrayList(); + ByteBuffer bytes = ByteBuffer.allocate(1000); + bytes.putInt(id); + bytes.putInt(flags); + bytes.putInt(actions); + bytes.putInt(maxValueLength); + bytes.putInt(currentValueLength); + bytes.putInt(textSelectionBase); + bytes.putInt(textSelectionExtent); + bytes.putInt(platformViewId); + bytes.putInt(scrollChildren); + bytes.putInt(scrollIndex); + bytes.putFloat(scrollPosition); + bytes.putFloat(scrollExtentMax); + bytes.putFloat(scrollExtentMin); + updateString(label, bytes, strings); + updateString(value, bytes, strings); + updateString(increasedValue, bytes, strings); + updateString(decreasedValue, bytes, strings); + updateString(hint, bytes, strings); + bytes.putInt(textDirection); + bytes.putFloat(left); + bytes.putFloat(top); + bytes.putFloat(right); + bytes.putFloat(bottom); + // transform. + for (int i = 0; i < 16; i++) { + bytes.putFloat(0); + } + // children in traversal order. + bytes.putInt(0); + // custom actions + bytes.putInt(0); + bytes.flip(); + return new TestSemanticsUpdate(bytes, strings.toArray(new String[strings.size()])); + } + } + + static void updateString(String value, ByteBuffer bytes, ArrayList strings) { + if (value == null) { + bytes.putInt(-1); + } else { + strings.add(value); + bytes.putInt(strings.size() - 1); + } + } +} From 6b883e9ff71912cc4456a82dfabb10d7957cf0d3 Mon Sep 17 00:00:00 2001 From: Ali Mahdiyar Date: Thu, 16 Apr 2020 13:18:21 +0430 Subject: [PATCH 26/39] Fix RTL handling in delete key event for android (#17393) --- .../editing/InputConnectionAdaptor.java | 33 +++---------------- .../editing/InputConnectionAdaptorTest.java | 29 ++++++++++++++++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java b/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java index d1b58039fb910..a990ff386108e 100644 --- a/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java +++ b/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java @@ -16,6 +16,7 @@ import android.text.Layout; import android.text.Selection; import android.text.TextPaint; +import android.text.method.TextKeyListener; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.BaseInputConnection; @@ -321,35 +322,11 @@ public boolean sendKeyEvent(KeyEvent event) { updateEditingState(); return true; } else if (selStart > 0) { - // Delete to the left/right of the cursor depending on direction of text. - // TODO(garyq): Explore how to obtain per-character direction. The - // isRTLCharAt() call below is returning blanket direction assumption - // based on the first character in the line. - boolean isRtl = mLayout.isRtlCharAt(mLayout.getLineForOffset(selStart)); - try { - if (isRtl) { - Selection.extendRight(mEditable, mLayout); - } else { - Selection.extendLeft(mEditable, mLayout); - } - } catch (IndexOutOfBoundsException e) { - // On some Chinese devices (primarily Huawei, some Xiaomi), - // on initial app startup before focus is lost, the - // Selection.extendLeft and extendRight calls always extend - // from the index of the initial contents of mEditable. This - // try-catch will prevent crashing on Huawei devices by falling - // back to a simple way of deletion, although this a hack and - // will not handle emojis. - Selection.setSelection(mEditable, selStart, selStart - 1); + if (TextKeyListener.getInstance().onKeyDown(null, mEditable, event.getKeyCode(), event)) { + updateEditingState(); + return true; } - int newStart = clampIndexToEditable(Selection.getSelectionStart(mEditable), mEditable); - int newEnd = clampIndexToEditable(Selection.getSelectionEnd(mEditable), mEditable); - Selection.setSelection(mEditable, Math.min(newStart, newEnd)); - // Min/Max the values since RTL selections will start at a higher - // index than they end at. - mEditable.delete(Math.min(newStart, newEnd), Math.max(newStart, newEnd)); - updateEditingState(); - return true; + return false; } } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) { int selStart = Selection.getSelectionStart(mEditable); diff --git a/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java b/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java index bf0f513a0835e..bbca2464a6232 100644 --- a/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java +++ b/shell/platform/android/test/io/flutter/plugin/editing/InputConnectionAdaptorTest.java @@ -313,15 +313,44 @@ public void inputConnectionAdaptor_RepeatFilter() throws NullPointerException { assertEquals(textInputChannel.selectionEnd, 4); } + @Test + public void testSendKeyEvent_delKeyDeletesBackward() { + int selStart = 29; + Editable editable = sampleRtlEditable(selStart, selStart); + InputConnectionAdaptor adaptor = sampleInputConnectionAdaptor(editable); + + KeyEvent downKeyDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL); + + for (int i = 0; i < 9; i++) { + boolean didConsume = adaptor.sendKeyEvent(downKeyDown); + assertTrue(didConsume); + } + assertEquals(Selection.getSelectionStart(editable), 19); + + for (int i = 0; i < 9; i++) { + boolean didConsume = adaptor.sendKeyEvent(downKeyDown); + assertTrue(didConsume); + } + assertEquals(Selection.getSelectionStart(editable), 10); + } + private static final String SAMPLE_TEXT = "Lorem ipsum dolor sit amet," + "\nconsectetur adipiscing elit."; + private static final String SAMPLE_RTL_TEXT = "متن ساختگی" + "\nبرای تستfor test😊"; + private static Editable sampleEditable(int selStart, int selEnd) { SpannableStringBuilder sample = new SpannableStringBuilder(SAMPLE_TEXT); Selection.setSelection(sample, selStart, selEnd); return sample; } + private static Editable sampleRtlEditable(int selStart, int selEnd) { + SpannableStringBuilder sample = new SpannableStringBuilder(SAMPLE_RTL_TEXT); + Selection.setSelection(sample, selStart, selEnd); + return sample; + } + private static InputConnectionAdaptor sampleInputConnectionAdaptor(Editable editable) { View testView = new View(RuntimeEnvironment.application); int client = 0; From 82fec3e99733da6f6d77fed61ec971667fde85c8 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 05:30:02 -0400 Subject: [PATCH 27/39] Roll src/third_party/dart d5c38cd35486..983f882180cd (8 commits) (#17747) --- DEPS | 8 +- ci/licenses_golden/licenses_third_party | 1068 +---------------------- sky/packages/sky_engine/LICENSE | 444 ---------- 3 files changed, 7 insertions(+), 1513 deletions(-) diff --git a/DEPS b/DEPS index 4da05e532ca53..9c22e48d2618d 100644 --- a/DEPS +++ b/DEPS @@ -34,7 +34,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS. # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'd5c38cd35486bbe6f7c77a9c013db6eb82683a23', + 'dart_revision': '983f882180cdfec98b9e2dde5a0e3fb013c93ebf', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py @@ -70,7 +70,6 @@ vars = { 'dart_mockito_tag': 'd39ac507483b9891165e422ec98d9fb480037c8b', 'dart_mustache_tag': '5e81b12215566dbe2473b2afd01a8a8aedd56ad9', 'dart_oauth2_tag': '1.2.1', - 'dart_observatory_pub_packages_rev': '0894122173b0f98eb08863a7712e78407d4477bc', 'dart_package_config_tag': 'v1.9.2', 'dart_path_tag': '1.7.0', 'dart_pedantic_tag': 'v1.9.0', @@ -196,9 +195,6 @@ deps = { 'src/third_party/dart/pkg/analysis_server/language_model': {'packages': [{'version': 'lIRt14qoA1Cocb8j3yw_Fx5cfYou2ddam6ArBm4AI6QC', 'package': 'dart/language_model'}], 'dep_type': 'cipd'}, - 'src/third_party/dart/third_party/observatory_pub_packages': - Var('dart_git') + '/observatory_pub_packages.git' + '@' + Var('dart_observatory_pub_packages_rev'), - 'src/third_party/dart/third_party/pkg/args': Var('dart_git') + '/args.git' + '@' + Var('dart_args_tag'), @@ -233,7 +229,7 @@ deps = { Var('dart_git') + '/dart2js_info.git' + '@' + Var('dart_dart2js_info_tag'), 'src/third_party/dart/third_party/pkg/dartdoc': - Var('dart_git') + '/dartdoc.git@v0.30.3', + Var('dart_git') + '/dartdoc.git@v0.30.4', 'src/third_party/dart/third_party/pkg/ffi': Var('dart_git') + '/ffi.git' + '@' + Var('dart_ffi_tag'), diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index e3e8741eb8c29..feb088981aa49 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: 3f705f1fbf9d8aa782e8b233788ff513 +Signature: f1e6cd4d252f4c3b58ed527d376118d4 UNUSED LICENSES: @@ -68,10 +68,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== ==================================================================================================== -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/dart_internal/LICENSE +ORIGIN: ../../../third_party/pkg/when/LICENSE TYPE: LicenseType.bsd ---------------------------------------------------------------------------------------------------- -Copyright 2017, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -543,7 +543,6 @@ POSSIBILITY OF SUCH DAMAGE. LIBRARY: angle LIBRARY: boringssl LIBRARY: khronos -LIBRARY: observatory_pub_packages LIBRARY: vulkan LIBRARY: wuffs ORIGIN: ../../../flutter/third_party/txt/LICENSE @@ -617,54 +616,6 @@ FILE: ../../../third_party/boringssl/src/third_party/wycheproof_testvectors/rsa_ FILE: ../../../third_party/boringssl/src/third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.json FILE: ../../../third_party/boringssl/src/third_party/wycheproof_testvectors/rsa_signature_test.json FILE: ../../../third_party/boringssl/src/third_party/wycheproof_testvectors/x25519_test.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/async.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/cache.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/check.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/collection.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/core.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/io.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/iterables.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/mirrors.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/pattern.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/collect.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/concat.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/countdown_timer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/enumerate.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/future_stream.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/iteration.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/metronome.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/stream_buffer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/async/stream_router.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/cache/cache.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/cache/map_cache.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/bimap.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/delegates/iterable.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/delegates/list.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/delegates/map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/delegates/queue.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/delegates/set.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/lru_map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/multimap.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/collection/treeset.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/core/hash.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/core/optional.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/concat.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/count.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/cycle.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/enumerate.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/generating_iterable.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/infinite_iterable.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/merge.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/min_max.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/partition.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/range.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/iterables/zip.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/pattern/glob.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/time/clock.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/time/duration_unit_constants.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/src/time/util.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/strings.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/quiver/lib/time.dart FILE: ../../../third_party/khronos/GLES2/gl2platform.h FILE: ../../../third_party/khronos/GLES3/gl3platform.h FILE: ../../../third_party/vulkan/include/vulkan/vk_platform.h @@ -20651,16 +20602,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== ==================================================================================================== -LIBRARY: observatory_pub_packages LIBRARY: pkg -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/comparators.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/LICENSE +ORIGIN: ../../../third_party/pkg/when/lib/when.dart + ../../../third_party/pkg/when/LICENSE TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/comparators.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/unparsed_frame.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/expected_function.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/group_context.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/example/example.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/example/example.html FILE: ../../../third_party/pkg/when/lib/when.dart ---------------------------------------------------------------------------------------------------- Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file @@ -20693,1008 +20637,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/.test_config -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/.test_config -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/.test_config -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/.analysis_options ----------------------------------------------------------------------------------------------------- -Copyright 2014, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/lib/dart.js + ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/lib/dart.js -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/lib/interop.js -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/algorithms.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/collection.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/equality.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/iterable_zip.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/algorithms.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/equality.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/iterable_zip.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/unmodifiable_wrappers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/wrappers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/wrappers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/pretty_print.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/context.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/parsed_path.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/path_exception.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/style.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/style/posix.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/style/url.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/style/windows.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/chain.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/frame.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/lazy_trace.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/stack_zone_specification.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/trace.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/vm_trace.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/stack_trace.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/compact_vm_config.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/html_config.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/html_enhanced_config.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/html_individual_config.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/configuration.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/pretty_print.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/simple_configuration.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/test_case.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/unittest.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/vm_config.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/.analysis_options -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/charted-demo-screenshot.png -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/components/demo_chartstate.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/components/demo_chartstate.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/components/demo_custom_axis.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/demo_charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/demo_interactive.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_bar_charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_bar_charts.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_cartesian_renderers.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_combo_charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_combo_charts.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_line_charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_line_charts.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_pie_charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_pie_charts.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_stacked_bar_charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_stacked_bar_charts.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/index.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/layout/treemap_demo.html -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/selection/transitions_demo.html ----------------------------------------------------------------------------------------------------- -Copyright (c) 2014, Michael Bostock and Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/components/demo_custom_axis.dart -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/components/demo_custom_axis.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/demo_interactive.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/charts/renderers/demo_cartesian_renderers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/layout/treemap_demo.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/examples/selection/transitions_demo.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charted.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/behaviors/axis_label_tooltip.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/behaviors/chart_tooltip.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/behaviors/hovercard.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/behaviors/line_marker.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/behaviors/mouse_tracker.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/cartesian_renderers/bar_chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/cartesian_renderers/bubble_chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/cartesian_renderers/cartesian_base_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/cartesian_renderers/stackedbar_chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/cartesian_renderers/stackedline_chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_area.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_config.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_data.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_events.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_legend.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_series.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_state.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/chart_theme.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/charts.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/data_transformers/aggregation.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/data_transformers/aggregation_item.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/data_transformers/aggregation_transformer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/data_transformers/filter_transformer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/data_transformers/transpose_transformer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/layout_renderers/layout_base_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/layout_renderers/pie_chart_renderer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/cartesian_area_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_axis_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_config_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_data_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_events_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_legend_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_series_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/chart_state_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/src/layout_area_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/charts/themes/quantum_theme.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/interpolators.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/interpolators/easing.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/interpolators/interpolators.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/scales.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/scales/linear_scale.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/scales/log_scale.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/scales/ordinal_scale.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/scales/time_scale.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/text_metrics.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/text_metrics/segmentation.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/text_metrics/segmentation_data.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/text_metrics/segmentation_utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/time_interval.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/timer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/bidi_formatter.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/color.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/disposer.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/lists.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/math.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/namespace.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/object_factory.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/core/utils/rect.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/layout/layout.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/layout/src/hierarchy_layout.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/layout/src/pie_layout.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/layout/src/treemap_layout.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/locale/format.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/locale/format/number_format.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/locale/format/time_format.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/locale/languages/en_us.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/locale/locale.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/selection/selection.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/selection/selection_scope.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/selection/src/selection_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/selection/src/transition_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/selection/transition.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/svg/axis.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/svg/shapes.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/svg/shapes/arc.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/svg/shapes/area.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/svg/shapes/line.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/lib/svg/shapes/rect.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/tool/build_unicode_segmentation_data.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/charted/tool/hop_runner.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2013, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -* Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/.test_config ----------------------------------------------------------------------------------------------------- -Copyright 2015, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/canonicalized_map.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/priority_queue.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/canonicalized_map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/priority_queue.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/queue_list.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/.status -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_time_patterns.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/logging/.status -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/mirror_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/util.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/benchmark/benchmark.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/characters.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/internal_style.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/.status -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/internal_test_case.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/prints_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/throws_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/throws_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/util.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/test_environment.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/example/ga.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/src/usage_impl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/src/usage_impl_html.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/src/usage_impl_io.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/usage.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/usage_html.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/usage_io.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/lib/uuid/uuid.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/usage/tool/grind.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/combined_wrappers/combined_iterable.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/combined_wrappers/combined_iterable.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/combined_wrappers/combined_list.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/combined_wrappers/combined_map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/dart_internal/lib/extract_type_arguments.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/meta/lib/dart2js.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/stack_trace/lib/src/lazy_chain.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/empty_unmodifiable_set.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/empty_unmodifiable_set.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/equality_map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/equality_set.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/functions.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/union_set.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/collection/lib/src/union_set_controller.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/compact_number_format.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/plural_rules.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/order_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/meta/lib/meta.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/observable.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/differs.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/differs/list_differ.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/differs/map_differ.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/internal.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/observable.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/observable_list.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/observable_map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/records.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/records/list_change_record.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/records/map_change_record.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/records/property_change_record.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/to_observable.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/af.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/am.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ar.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ar_DZ.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/az.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/be.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/bg.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/bn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/br.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/bs.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ca.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/chr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/cs.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/cy.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/da.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/de.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/de_AT.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/de_CH.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/el.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_AU.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_CA.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_GB.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_IE.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_IN.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_ISO.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_MY.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_SG.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_US.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/en_ZA.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/es.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/es_419.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/es_ES.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/es_MX.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/es_US.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/et.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/eu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/fa.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/fi.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/fil.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/fr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/fr_CA.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/fr_CH.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ga.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/gl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/gsw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/gu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/haw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/he.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/hi.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/hr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/hu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/hy.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/id.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/in.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/is.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/it.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/it_CH.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/iw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ja.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ka.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/kk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/km.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/kn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ko.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ky.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ln.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/lo.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/lt.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/lv.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/mk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ml.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/mn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/mo.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/mr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ms.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/mt.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/my.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/nb.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ne.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/nl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/no.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/no_NO.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/or.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/pa.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/pl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ps.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/pt.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/pt_BR.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/pt_PT.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ro.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ru.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sd.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sh.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/si.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sq.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sr_Latn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sv.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/sw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ta.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/te.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/th.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/tl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/tr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/uk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/ur.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/uz.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/vi.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/zh.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/zh_CN.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/zh_HK.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/zh_TW.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/patterns/zu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/af.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/am.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ar.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ar_DZ.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/az.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/be.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/bg.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/bn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/br.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/bs.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ca.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/chr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/cs.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/cy.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/da.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/de.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/de_AT.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/de_CH.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/el.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_AU.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_CA.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_GB.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_IE.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_IN.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_ISO.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_MY.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_SG.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_US.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/en_ZA.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/es.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/es_419.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/es_ES.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/es_MX.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/es_US.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/et.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/eu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/fa.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/fi.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/fil.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/fr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/fr_CA.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/fr_CH.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ga.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/gl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/gsw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/gu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/haw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/he.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/hi.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/hr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/hu.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/hy.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/id.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/in.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/is.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/it.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/it_CH.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/iw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ja.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ka.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/kk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/km.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/kn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ko.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ky.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ln.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/lo.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/lt.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/lv.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/mk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ml.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/mn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/mr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ms.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/mt.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/my.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/nb.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ne.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/nl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/no.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/no_NO.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/or.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/pa.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/pl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ps.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/pt.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/pt_BR.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/pt_PT.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ro.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ru.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/si.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sq.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sr_Latn.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sv.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/sw.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ta.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/te.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/th.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/tl.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/tr.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/uk.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/ur.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/uz.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/vi.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/zh.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/zh_CN.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/zh_HK.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/zh_TW.json -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/symbols/zu.json ----------------------------------------------------------------------------------------------------- -Copyright 2013, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbol_data_custom.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbol_data_custom.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2017, the Dart project authors. -Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbol_data_local.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbol_data_local.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/number_symbols_data.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2014, the Dart project authors. -Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/locale_list.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbol_data_file.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbol_data_http_request.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/date_symbols.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/intl.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/intl_browser.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/intl_standalone.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/message_lookup_by_library.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/number_symbols.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/data/dates/locale_list.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/date_format_internal.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/file_data_reader.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/http_request_data_reader.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/bidi_formatter.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/bidi_utils.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/date_format.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/date_format_field.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/date_format_helpers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl/number_format.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/intl_helpers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/lib/src/lazy_locale_data.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/intl/tool/generate_locale_data_files.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/logging/lib/logging.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/core_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/custom_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/description.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/error_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/interfaces.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/iterable_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/map_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/numeric_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/operator_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/string_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/path.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/core_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/description.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/error_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/expect.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/future_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/interfaces.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/iterable_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/map_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/numeric_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/operator_matchers.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/src/matcher/string_matchers.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/equals_matcher.dart + ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/equals_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/feature_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/having_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/matcher/lib/src/type_matcher.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/path_map.dart -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/path/lib/src/path_set.dart ----------------------------------------------------------------------------------------------------- -Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/meta/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/observable/lib/src/change_notifier.dart ----------------------------------------------------------------------------------------------------- -Copyright 2016, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - -==================================================================================================== -LIBRARY: observatory_pub_packages -ORIGIN: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/coverage_controller.js + ../../../third_party/dart/third_party/observatory_pub_packages/packages/browser/LICENSE -TYPE: LicenseType.bsd -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/coverage_controller.js -FILE: ../../../third_party/dart/third_party/observatory_pub_packages/packages/unittest/lib/test_controller.js ----------------------------------------------------------------------------------------------------- -Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -==================================================================================================== - ==================================================================================================== LIBRARY: rapidjson ORIGIN: ../../../third_party/rapidjson/LICENSE @@ -23754,4 +22696,4 @@ freely, subject to the following restrictions: misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ==================================================================================================== -Total license count: 370 +Total license count: 355 diff --git a/sky/packages/sky_engine/LICENSE b/sky/packages/sky_engine/LICENSE index fca14e2785127..735a9fd2a6797 100644 --- a/sky/packages/sky_engine/LICENSE +++ b/sky/packages/sky_engine/LICENSE @@ -423,7 +423,6 @@ boringssl engine etc1 khronos -observatory_pub_packages txt vulkan wuffs @@ -10259,449 +10258,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2013, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -* Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2014, Michael Bostock and Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2014, the Dart project authors. -Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2017, the Dart project authors. -Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -for details. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright 2013, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright 2014, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright 2015, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages - -Copyright 2016, the Dart project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -observatory_pub_packages pkg Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file From 104df6bba4c2a0ca97d60aa85dcbd697cd3836fb Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Thu, 16 Apr 2020 02:47:53 -0700 Subject: [PATCH 28/39] Add autofill support to ios text input plugin (#17493) --- .../ios/framework/Source/FlutterEngine.mm | 5 + .../Source/FlutterTextInputDelegate.h | 1 + .../framework/Source/FlutterTextInputPlugin.h | 4 +- .../Source/FlutterTextInputPlugin.mm | 282 +++++++++++++++--- .../Source/FlutterTextInputPluginTest.m | 61 ++++ 5 files changed, 304 insertions(+), 49 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index c3302194b039a..35cf9553b0c61 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -534,6 +534,11 @@ - (void)updateEditingClient:(int)client withState:(NSDictionary*)state { arguments:@[ @(client), state ]]; } +- (void)updateEditingClient:(int)client withState:(NSDictionary*)state withTag:(NSString*)tag { + [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingStateWithTag" + arguments:@[ @(client), @{tag : state} ]]; +} + - (void)updateFloatingCursor:(FlutterFloatingCursorDragState)state withClient:(int)client withPosition:(NSDictionary*)position { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h b/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h index 8446a79946d63..033a196696127 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h @@ -30,6 +30,7 @@ typedef NS_ENUM(NSInteger, FlutterFloatingCursorDragState) { @protocol FlutterTextInputDelegate - (void)updateEditingClient:(int)client withState:(NSDictionary*)state; +- (void)updateEditingClient:(int)client withState:(NSDictionary*)state withTag:(NSString*)tag; - (void)performAction:(FlutterTextInputAction)action withClient:(int)client; - (void)updateFloatingCursor:(FlutterFloatingCursorDragState)state withClient:(int)client diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h index 3677c0f78284a..c5571ee10e0b3 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h @@ -36,9 +36,6 @@ @end /** A range of text in the buffer of a Flutter text editing widget. */ -#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG -FLUTTER_EXPORT -#endif @interface FlutterTextRange : UITextRange @property(nonatomic, readonly) NSRange range; @@ -71,6 +68,7 @@ FLUTTER_EXPORT @property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry; @property(nonatomic) UITextSmartQuotesType smartQuotesType API_AVAILABLE(ios(11.0)); @property(nonatomic) UITextSmartDashesType smartDashesType API_AVAILABLE(ios(11.0)); +@property(nonatomic, copy) UITextContentType textContentType API_AVAILABLE(ios(10.0)); @property(nonatomic, assign) id textInputDelegate; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index f9ddd6621d6d8..068b8bcb76622 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -88,6 +88,122 @@ static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) { return UIReturnKeyDefault; } +static UITextContentType ToUITextContentType(NSArray* hints) { + if (hints == nil || hints.count == 0) { + return @""; + } + + NSString* hint = hints[0]; + if (@available(iOS 10.0, *)) { + if ([hint isEqualToString:@"addressCityAndState"]) { + return UITextContentTypeAddressCityAndState; + } + + if ([hint isEqualToString:@"addressState"]) { + return UITextContentTypeAddressState; + } + + if ([hint isEqualToString:@"addressCity"]) { + return UITextContentTypeAddressCity; + } + + if ([hint isEqualToString:@"sublocality"]) { + return UITextContentTypeSublocality; + } + + if ([hint isEqualToString:@"streetAddressLine1"]) { + return UITextContentTypeStreetAddressLine1; + } + + if ([hint isEqualToString:@"streetAddressLine2"]) { + return UITextContentTypeStreetAddressLine2; + } + + if ([hint isEqualToString:@"countryName"]) { + return UITextContentTypeCountryName; + } + + if ([hint isEqualToString:@"fullStreetAddress"]) { + return UITextContentTypeFullStreetAddress; + } + + if ([hint isEqualToString:@"postalCode"]) { + return UITextContentTypePostalCode; + } + + if ([hint isEqualToString:@"location"]) { + return UITextContentTypeLocation; + } + + if ([hint isEqualToString:@"creditCardNumber"]) { + return UITextContentTypeCreditCardNumber; + } + + if ([hint isEqualToString:@"email"]) { + return UITextContentTypeEmailAddress; + } + + if ([hint isEqualToString:@"jobTitle"]) { + return UITextContentTypeJobTitle; + } + + if ([hint isEqualToString:@"givenName"]) { + return UITextContentTypeGivenName; + } + + if ([hint isEqualToString:@"middleName"]) { + return UITextContentTypeMiddleName; + } + + if ([hint isEqualToString:@"familyName"]) { + return UITextContentTypeFamilyName; + } + + if ([hint isEqualToString:@"name"]) { + return UITextContentTypeName; + } + + if ([hint isEqualToString:@"namePrefix"]) { + return UITextContentTypeNamePrefix; + } + + if ([hint isEqualToString:@"nameSuffix"]) { + return UITextContentTypeNameSuffix; + } + + if ([hint isEqualToString:@"nickname"]) { + return UITextContentTypeNickname; + } + + if ([hint isEqualToString:@"organizationName"]) { + return UITextContentTypeOrganizationName; + } + + if ([hint isEqualToString:@"telephoneNumber"]) { + return UITextContentTypeTelephoneNumber; + } + } + + if (@available(iOS 11.0, *)) { + if ([hint isEqualToString:@"password"]) { + return UITextContentTypePassword; + } + } + + if (@available(iOS 12.0, *)) { + if ([hint isEqualToString:@"oneTimeCode"]) { + return UITextContentTypeOneTimeCode; + } + } + + return hints[0]; +} + +static NSString* uniqueIdFromDictionary(NSDictionary* dictionary) { + NSDictionary* autofill = dictionary[@"autofill"]; + return autofill == nil ? nil : autofill[@"uniqueIdentifier"]; +} + #pragma mark - FlutterTextPosition @implementation FlutterTextPosition @@ -140,6 +256,10 @@ - (id)copyWithZone:(NSZone*)zone { @end +@interface FlutterTextInputView () +@property(nonatomic, copy) NSString* autofillId; +@end + @implementation FlutterTextInputView { int _textInputClient; const char* _selectionAffinity; @@ -184,6 +304,7 @@ - (void)dealloc { [_markedTextRange release]; [_selectedTextRange release]; [_tokenizer release]; + [_autofillId release]; [super dealloc]; } @@ -241,7 +362,10 @@ - (NSRange)clampSelection:(NSRange)range forText:(NSString*)text { #pragma mark - UIResponder Overrides - (BOOL)canBecomeFirstResponder { - return YES; + // Only the currently focused input field can + // become the first responder. This prevents iOS + // from changing focus by itself. + return _textInputClient != 0; } #pragma mark - UITextInput Overrides @@ -600,16 +724,22 @@ - (void)updateEditingState { composingBase = ((FlutterTextPosition*)self.markedTextRange.start).index; composingExtent = ((FlutterTextPosition*)self.markedTextRange.end).index; } - [_textInputDelegate updateEditingClient:_textInputClient - withState:@{ - @"selectionBase" : @(selectionBase), - @"selectionExtent" : @(selectionExtent), - @"selectionAffinity" : @(_selectionAffinity), - @"selectionIsDirectional" : @(false), - @"composingBase" : @(composingBase), - @"composingExtent" : @(composingExtent), - @"text" : [NSString stringWithString:self.text], - }]; + + NSDictionary* state = @{ + @"selectionBase" : @(selectionBase), + @"selectionExtent" : @(selectionExtent), + @"selectionAffinity" : @(_selectionAffinity), + @"selectionIsDirectional" : @(false), + @"composingBase" : @(composingBase), + @"composingExtent" : @(composingExtent), + @"text" : [NSString stringWithString:self.text], + }; + + if (_textInputClient == 0 && _autofillId != nil) { + [_textInputDelegate updateEditingClient:_textInputClient withState:state withTag:_autofillId]; + } else { + [_textInputDelegate updateEditingClient:_textInputClient withState:state]; + } } - (BOOL)hasText { @@ -671,12 +801,15 @@ - (BOOL)accessibilityElementsHidden { @end -@implementation FlutterTextInputPlugin { - FlutterTextInputView* _view; - FlutterTextInputView* _secureView; - FlutterTextInputView* _activeView; - FlutterTextInputViewAccessibilityHider* _inputHider; -} +@interface FlutterTextInputPlugin () +@property(nonatomic, retain) FlutterTextInputView* nonAutofillInputView; +@property(nonatomic, retain) FlutterTextInputView* nonAutofillSecureInputView; +@property(nonatomic, retain) NSMutableArray* inputViews; +@property(nonatomic, assign) FlutterTextInputView* activeView; +@property(nonatomic, retain) FlutterTextInputViewAccessibilityHider* inputHider; +@end + +@implementation FlutterTextInputPlugin @synthesize textInputDelegate = _textInputDelegate; @@ -684,12 +817,13 @@ - (instancetype)init { self = [super init]; if (self) { - _view = [[FlutterTextInputView alloc] init]; - _view.secureTextEntry = NO; - _secureView = [[FlutterTextInputView alloc] init]; - _secureView.secureTextEntry = YES; + _nonAutofillInputView = [[FlutterTextInputView alloc] init]; + _nonAutofillInputView.secureTextEntry = NO; + _nonAutofillInputView = [[FlutterTextInputView alloc] init]; + _nonAutofillSecureInputView.secureTextEntry = YES; + _inputViews = [[NSMutableArray alloc] init]; - _activeView = _view; + _activeView = _nonAutofillInputView; _inputHider = [[FlutterTextInputViewAccessibilityHider alloc] init]; } @@ -698,9 +832,10 @@ - (instancetype)init { - (void)dealloc { [self hideTextInput]; - [_view release]; - [_secureView release]; + [_nonAutofillInputView release]; + [_nonAutofillSecureInputView release]; [_inputHider release]; + [_inputViews release]; [super dealloc]; } @@ -733,58 +868,113 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } - (void)showTextInput { - NSAssert([UIApplication sharedApplication].keyWindow != nullptr, + UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow; + NSAssert(keyWindow != nullptr, @"The application must have a key window since the keyboard client " @"must be part of the responder chain to function"); _activeView.textInputDelegate = _textInputDelegate; - [_inputHider addSubview:_activeView]; - [[UIApplication sharedApplication].keyWindow addSubview:_inputHider]; + if (![_activeView isDescendantOfView:_inputHider]) { + [_inputHider addSubview:_activeView]; + } + [keyWindow addSubview:_inputHider]; [_activeView becomeFirstResponder]; } - (void)hideTextInput { [_activeView resignFirstResponder]; - [_activeView removeFromSuperview]; [_inputHider removeFromSuperview]; } - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configuration { - NSDictionary* inputType = configuration[@"inputType"]; - NSString* keyboardAppearance = configuration[@"keyboardAppearance"]; - if ([configuration[@"obscureText"] boolValue]) { - _activeView = _secureView; + NSArray* fields = configuration[@"fields"]; + NSString* clientUniqueId = uniqueIdFromDictionary(configuration); + bool isSecureTextEntry = [configuration[@"obscureText"] boolValue]; + + if (fields == nil) { + _activeView = isSecureTextEntry ? _nonAutofillSecureInputView : _nonAutofillInputView; + [FlutterTextInputPlugin setupInputView:_activeView withConfiguration:configuration]; + + if (![_activeView isDescendantOfView:_inputHider]) { + [_inputHider addSubview:_activeView]; + } } else { - _activeView = _view; + NSAssert(clientUniqueId != nil, @"The client's unique id can't be null"); + for (FlutterTextInputView* view in _inputViews) { + [view removeFromSuperview]; + } + for (UIView* subview in _inputHider.subviews) { + [subview removeFromSuperview]; + } + + [_inputViews removeAllObjects]; + + for (NSDictionary* field in fields) { + FlutterTextInputView* newInputView = [[[FlutterTextInputView alloc] init] autorelease]; + newInputView.textInputDelegate = _textInputDelegate; + [_inputViews addObject:newInputView]; + + NSString* autofillId = uniqueIdFromDictionary(field); + newInputView.autofillId = autofillId; + + if ([clientUniqueId isEqualToString:autofillId]) { + _activeView = newInputView; + } + + [FlutterTextInputPlugin setupInputView:newInputView withConfiguration:field]; + [_inputHider addSubview:newInputView]; + } } - _activeView.keyboardType = ToUIKeyboardType(inputType); - _activeView.returnKeyType = ToUIReturnKeyType(configuration[@"inputAction"]); - _activeView.autocapitalizationType = ToUITextAutoCapitalizationType(configuration); + [_activeView setTextInputClient:client]; + [_activeView reloadInputViews]; +} + ++ (void)setupInputView:(FlutterTextInputView*)inputView + withConfiguration:(NSDictionary*)configuration { + NSDictionary* inputType = configuration[@"inputType"]; + NSString* keyboardAppearance = configuration[@"keyboardAppearance"]; + NSDictionary* autofill = configuration[@"autofill"]; + + inputView.secureTextEntry = [configuration[@"obscureText"] boolValue]; + inputView.keyboardType = ToUIKeyboardType(inputType); + inputView.returnKeyType = ToUIReturnKeyType(configuration[@"inputAction"]); + inputView.autocapitalizationType = ToUITextAutoCapitalizationType(configuration); + if (@available(iOS 11.0, *)) { NSString* smartDashesType = configuration[@"smartDashesType"]; // This index comes from the SmartDashesType enum in the framework. bool smartDashesIsDisabled = smartDashesType && [smartDashesType isEqualToString:@"0"]; - _activeView.smartDashesType = + inputView.smartDashesType = smartDashesIsDisabled ? UITextSmartDashesTypeNo : UITextSmartDashesTypeYes; NSString* smartQuotesType = configuration[@"smartQuotesType"]; // This index comes from the SmartQuotesType enum in the framework. bool smartQuotesIsDisabled = smartQuotesType && [smartQuotesType isEqualToString:@"0"]; - _activeView.smartQuotesType = + inputView.smartQuotesType = smartQuotesIsDisabled ? UITextSmartQuotesTypeNo : UITextSmartQuotesTypeYes; } if ([keyboardAppearance isEqualToString:@"Brightness.dark"]) { - _activeView.keyboardAppearance = UIKeyboardAppearanceDark; + inputView.keyboardAppearance = UIKeyboardAppearanceDark; } else if ([keyboardAppearance isEqualToString:@"Brightness.light"]) { - _activeView.keyboardAppearance = UIKeyboardAppearanceLight; + inputView.keyboardAppearance = UIKeyboardAppearanceLight; } else { - _activeView.keyboardAppearance = UIKeyboardAppearanceDefault; + inputView.keyboardAppearance = UIKeyboardAppearanceDefault; } NSString* autocorrect = configuration[@"autocorrect"]; - _activeView.autocorrectionType = autocorrect && ![autocorrect boolValue] - ? UITextAutocorrectionTypeNo - : UITextAutocorrectionTypeDefault; - [_activeView setTextInputClient:client]; - [_activeView reloadInputViews]; + inputView.autocorrectionType = autocorrect && ![autocorrect boolValue] + ? UITextAutocorrectionTypeNo + : UITextAutocorrectionTypeDefault; + if (@available(iOS 10.0, *)) { + if (autofill == nil) { + inputView.textContentType = @""; + } else { + inputView.textContentType = ToUITextContentType(autofill[@"hints"]); + [inputView setTextInputState:autofill[@"editingValue"]]; + // An input field needs to be visible in order to get + // autofilled when it's not the one that triggered + // autofill. + inputView.frame = CGRectMake(0, 0, 1, 1); + } + } } - (void)setTextInputEditingState:(NSDictionary*)state { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m index 5355e92fa3adc..df6e1a5a2fb8b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m @@ -15,6 +15,67 @@ @interface FlutterTextInputPluginTest : XCTestCase @implementation FlutterTextInputPluginTest +- (void)testAutofillInputViews { + // Setup test. + id engine = OCMClassMock([FlutterEngine class]); + FlutterTextInputPlugin* textInputPlugin = [[FlutterTextInputPlugin alloc] init]; + textInputPlugin.textInputDelegate = engine; + + NSDictionary* template = @{ + @"inputType" : @{@"name" : @"TextInuptType.text"}, + @"keyboardAppearance" : @"Brightness.light", + @"obscureText" : @NO, + @"inputAction" : @"TextInputAction.unspecified", + @"smartDashesType" : @"0", + @"smartQuotesType" : @"0", + @"autocorrect" : @YES + }; + + NSMutableDictionary* field1 = [template mutableCopy]; + [field1 setValue:@{ + @"uniqueIdentifier" : @"field1", + @"hints" : @[ @"hint1" ], + @"editingValue" : @{@"text" : @""} + } + forKey:@"autofill"]; + + NSMutableDictionary* field2 = [template mutableCopy]; + [field2 setValue:@{ + @"uniqueIdentifier" : @"field2", + @"hints" : @[ @"hint2" ], + @"editingValue" : @{@"text" : @""} + } + forKey:@"autofill"]; + + NSMutableDictionary* config = [field1 mutableCopy]; + [config setValue:@[ field1, field2 ] forKey:@"fields"]; + + FlutterMethodCall* setClientCall = + [FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ @123, config ]]; + + [textInputPlugin handleMethodCall:setClientCall + result:^(id _Nullable result){ + }]; + + // Find all input views in the input hider view. + NSArray* inputFields = + [[[textInputPlugin textInputView] superview] subviews]; + + XCTAssertEqual(inputFields.count, 2); + + // Find the inactive autofillable input field. + FlutterTextInputView* inactiveView = inputFields[1]; + [inactiveView replaceRange:[FlutterTextRange rangeWithNSRange:NSMakeRange(0, 0)] + withText:@"Autofilled!"]; + + // Verify behavior. + OCMVerify([engine updateEditingClient:0 withState:[OCMArg isNotNil] withTag:@"field2"]); + + // Clean up mocks + [engine stopMocking]; +} + - (void)testAutocorrectionPromptRectAppears { // Setup test. id engine = OCMClassMock([FlutterEngine class]); From cf3d738f50d8ee6fdc290a680b6bf73cad19d8a5 Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Thu, 16 Apr 2020 03:41:23 -0700 Subject: [PATCH 29/39] Android text input autofill (#17465) --- .../embedding/android/FlutterView.java | 17 ++ .../systemchannels/TextInputChannel.java | 205 +++++++++++++++++- .../plugin/editing/TextInputPlugin.java | 201 ++++++++++++++++- .../android/io/flutter/view/FlutterView.java | 14 ++ .../plugin/editing/TextInputPluginTest.java | 170 ++++++++++++++- 5 files changed, 592 insertions(+), 15 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 31cbeb9673484..33e50f295ae05 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -14,12 +14,15 @@ import android.os.LocaleList; import android.text.format.DateFormat; import android.util.AttributeSet; +import android.util.SparseArray; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewStructure; import android.view.WindowInsets; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeProvider; +import android.view.autofill.AutofillValue; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.widget.FrameLayout; @@ -283,6 +286,9 @@ private void init() { // FlutterView needs to be focusable so that the InputMethodManager can interact with it. setFocusable(true); setFocusableInTouchMode(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS); + } } /** @@ -898,6 +904,17 @@ private void sendViewportMetricsToFlutter() { flutterEngine.getRenderer().setViewportMetrics(viewportMetrics); } + @Override + public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { + super.onProvideAutofillVirtualStructure(structure, flags); + textInputPlugin.onProvideAutofillVirtualStructure(structure, flags); + } + + @Override + public void autofill(SparseArray values) { + textInputPlugin.autofill(values); + } + /** * Render modes for a {@link FlutterView}. * diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java index 80d2e419c8fce..a8fe0d5f95784 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java @@ -1,5 +1,7 @@ package io.flutter.embedding.engine.systemchannels; +import android.os.Build; +import android.view.View; import android.view.inputmethod.EditorInfo; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -10,6 +12,7 @@ import io.flutter.plugin.common.MethodChannel; import java.util.Arrays; import java.util.HashMap; +import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -85,6 +88,22 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; + case "TextInput.setEditableSizeAndTransform": + try { + final JSONObject arguments = (JSONObject) args; + final double width = arguments.getDouble("width"); + final double height = arguments.getDouble("height"); + final JSONArray jsonMatrix = arguments.getJSONArray("transform"); + final double[] matrix = new double[16]; + for (int i = 0; i < 16; i++) { + matrix[i] = jsonMatrix.getDouble(i); + } + + textInputMethodHandler.setEditableSizeAndTransform(width, height, matrix); + } catch (JSONException exception) { + result.error("error", exception.getMessage(), null); + } + break; case "TextInput.clearClient": textInputMethodHandler.clearClient(); result.success(null); @@ -119,6 +138,16 @@ public void requestExistingInputState() { channel.invokeMethod("TextInputClient.requestExistingInputState", null); } + private static HashMap createEditingStateJSON( + String text, int selectionStart, int selectionEnd, int composingStart, int composingEnd) { + HashMap state = new HashMap<>(); + state.put("text", text); + state.put("selectionBase", selectionStart); + state.put("selectionExtent", selectionEnd); + state.put("composingBase", composingStart); + state.put("composingExtent", composingEnd); + return state; + } /** * Instructs Flutter to update its text input editing state to reflect the given configuration. */ @@ -147,16 +176,31 @@ public void updateEditingState( + "Composing end: " + composingEnd); - HashMap state = new HashMap<>(); - state.put("text", text); - state.put("selectionBase", selectionStart); - state.put("selectionExtent", selectionEnd); - state.put("composingBase", composingStart); - state.put("composingExtent", composingEnd); + final HashMap state = + createEditingStateJSON(text, selectionStart, selectionEnd, composingStart, composingEnd); channel.invokeMethod("TextInputClient.updateEditingState", Arrays.asList(inputClientId, state)); } + public void updateEditingStateWithTag( + int inputClientId, HashMap editStates) { + Log.v( + TAG, + "Sending message to update editing state for " + + String.valueOf(editStates.size()) + + " field(s)."); + + final HashMap> json = new HashMap<>(); + for (Map.Entry element : editStates.entrySet()) { + final TextEditState state = element.getValue(); + json.put( + element.getKey(), + createEditingStateJSON(state.text, state.selectionStart, state.selectionEnd, -1, -1)); + } + channel.invokeMethod( + "TextInputClient.updateEditingStateWithTag", Arrays.asList(inputClientId, json)); + } + /** Instructs Flutter to execute a "newline" action. */ public void newline(int inputClientId) { Log.v(TAG, "Sending 'newline' message."); @@ -229,6 +273,13 @@ public interface TextInputMethodHandler { // TODO(mattcarroll): javadoc void hide(); + /** + * Requests that the autofill dropdown menu appear for the current client. + * + *

Has no effect if the current client does not support autofill. + */ + void requestAutofill(); + // TODO(mattcarroll): javadoc void setClient(int textInputClientId, @NonNull Configuration configuration); @@ -242,6 +293,16 @@ public interface TextInputMethodHandler { */ void setPlatformViewClient(int id); + /** + * Sets the size and the transform matrix of the current text input client. + * + * @param width the width of text input client. Must be finite. + * @param height the height of text input client. Must be finite. + * @param transform a 4x4 matrix that maps the local paint coordinate system to coordinate + * system of the FlutterView that owns the current client. + */ + void setEditableSizeAndTransform(double width, double height, double[] transform); + // TODO(mattcarroll): javadoc void setEditingState(@NonNull TextEditState editingState); @@ -257,7 +318,14 @@ public static Configuration fromJson(@NonNull JSONObject json) if (inputActionName == null) { throw new JSONException("Configuration JSON missing 'inputAction' property."); } - + Configuration[] fields = null; + if (!json.isNull("fields")) { + final JSONArray jsonFields = json.getJSONArray("fields"); + fields = new Configuration[jsonFields.length()]; + for (int i = 0; i < fields.length; i++) { + fields[i] = Configuration.fromJson(jsonFields.getJSONObject(i)); + } + } final Integer inputAction = inputActionFromTextInputAction(inputActionName); return new Configuration( json.optBoolean("obscureText"), @@ -266,7 +334,9 @@ public static Configuration fromJson(@NonNull JSONObject json) TextCapitalization.fromValue(json.getString("textCapitalization")), InputType.fromJson(json.getJSONObject("inputType")), inputAction, - json.isNull("actionLabel") ? null : json.getString("actionLabel")); + json.isNull("actionLabel") ? null : json.getString("actionLabel"), + json.isNull("autofill") ? null : Autofill.fromJson(json.getJSONObject("autofill")), + fields); } @NonNull @@ -296,6 +366,117 @@ private static Integer inputActionFromTextInputAction(@NonNull String inputActio } } + public static class Autofill { + public static Autofill fromJson(@NonNull JSONObject json) + throws JSONException, NoSuchFieldException { + final String uniqueIdentifier = json.getString("uniqueIdentifier"); + final JSONArray hints = json.getJSONArray("hints"); + final JSONObject editingState = json.getJSONObject("editingValue"); + final String[] hintList = new String[hints.length()]; + + for (int i = 0; i < hintList.length; i++) { + hintList[i] = translateAutofillHint(hints.getString(i)); + } + return new Autofill(uniqueIdentifier, hintList, TextEditState.fromJson(editingState)); + } + + public final String uniqueIdentifier; + public final String[] hints; + public final TextEditState editState; + + @NonNull + private static String translateAutofillHint(@NonNull String hint) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return hint; + } + switch (hint) { + case "addressCity": + return "addressLocality"; + case "addressState": + return "addressRegion"; + case "birthday": + return "birthDateFull"; + case "birthdayDay": + return "birthDateDay"; + case "birthdayMonth": + return "birthDateMonth"; + case "birthdayYear": + return "birthDateYear"; + case "countryName": + return "addressCountry"; + case "creditCardExpirationDate": + return View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE; + case "creditCardExpirationDay": + return View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY; + case "creditCardExpirationMonth": + return View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH; + case "creditCardExpirationYear": + return View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR; + case "creditCardNumber": + return View.AUTOFILL_HINT_CREDIT_CARD_NUMBER; + case "creditCardSecurityCode": + return View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE; + case "email": + return View.AUTOFILL_HINT_EMAIL_ADDRESS; + case "familyName": + return "personFamilyName"; + case "fullStreetAddress": + return "streetAddress"; + case "gender": + return "gender"; + case "givenName": + return "personGivenName"; + case "middleInitial": + return "personMiddleInitial"; + case "middleName": + return "personMiddleName"; + case "name": + return "personName"; + case "namePrefix": + return "personNamePrefix"; + case "nameSuffix": + return "personNameSuffix"; + case "newPassword": + return "newPassword"; + case "newUsername": + return "newUsername"; + case "oneTimeCode": + return "smsOTPCode"; + case "password": + return View.AUTOFILL_HINT_PASSWORD; + case "postalAddress": + return View.AUTOFILL_HINT_POSTAL_ADDRESS; + case "postalAddressExtended": + return "extendedAddress"; + case "postalAddressExtendedPostalCode": + return "extendedPostalCode"; + case "postalCode": + return View.AUTOFILL_HINT_POSTAL_CODE; + case "telephoneNumber": + return "phoneNumber"; + case "telephoneNumberCountryCode": + return "phoneCountryCode"; + case "telephoneNumberDevice": + return "phoneNumberDevice"; + case "telephoneNumberNational": + return "phoneNational"; + case "username": + return View.AUTOFILL_HINT_USERNAME; + default: + return hint; + } + } + + public Autofill( + @NonNull String uniqueIdentifier, + @NonNull String[] hints, + @NonNull TextEditState editingState) { + this.uniqueIdentifier = uniqueIdentifier; + this.hints = hints; + this.editState = editingState; + } + } + public final boolean obscureText; public final boolean autocorrect; public final boolean enableSuggestions; @@ -303,6 +484,8 @@ private static Integer inputActionFromTextInputAction(@NonNull String inputActio @NonNull public final InputType inputType; @Nullable public final Integer inputAction; @Nullable public final String actionLabel; + @Nullable public final Autofill autofill; + @Nullable public final Configuration[] fields; public Configuration( boolean obscureText, @@ -311,7 +494,9 @@ public Configuration( @NonNull TextCapitalization textCapitalization, @NonNull InputType inputType, @Nullable Integer inputAction, - @Nullable String actionLabel) { + @Nullable String actionLabel, + @Nullable Autofill autofill, + @Nullable Configuration[] fields) { this.obscureText = obscureText; this.autocorrect = autocorrect; this.enableSuggestions = enableSuggestions; @@ -319,6 +504,8 @@ public Configuration( this.inputType = inputType; this.inputAction = inputAction; this.actionLabel = actionLabel; + this.autofill = autofill; + this.fields = fields; } } diff --git a/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java b/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java index 17ccea06728de..b14ac4112f611 100644 --- a/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java +++ b/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java @@ -6,12 +6,18 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.Rect; import android.os.Build; import android.provider.Settings; import android.text.Editable; import android.text.InputType; import android.text.Selection; +import android.util.SparseArray; import android.view.View; +import android.view.ViewStructure; +import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; +import android.view.autofill.AutofillValue; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -23,18 +29,22 @@ import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.systemchannels.TextInputChannel; import io.flutter.plugin.platform.PlatformViewsController; +import java.util.HashMap; /** Android implementation of the text input plugin. */ public class TextInputPlugin { @NonNull private final View mView; @NonNull private final InputMethodManager mImm; + @NonNull private final AutofillManager afm; @NonNull private final TextInputChannel textInputChannel; @NonNull private InputTarget inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0); @Nullable private TextInputChannel.Configuration configuration; + @Nullable private SparseArray mAutofillConfigurations; @Nullable private Editable mEditable; private boolean mRestartInputPending; @Nullable private InputConnection lastInputConnection; @NonNull private PlatformViewsController platformViewsController; + @Nullable private Rect lastClientRect; private final boolean restartAlwaysRequired; // When true following calls to createInputConnection will return the cached lastInputConnection @@ -49,6 +59,11 @@ public TextInputPlugin( @NonNull PlatformViewsController platformViewsController) { mView = view; mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + afm = view.getContext().getSystemService(AutofillManager.class); + } else { + afm = null; + } textInputChannel = new TextInputChannel(dartExecutor); textInputChannel.setTextInputMethodHandler( @@ -63,6 +78,11 @@ public void hide() { hideTextInput(mView); } + @Override + public void requestAutofill() { + notifyViewEntered(); + } + @Override public void setClient( int textInputClientId, TextInputChannel.Configuration configuration) { @@ -79,6 +99,11 @@ public void setEditingState(TextInputChannel.TextEditState editingState) { setTextInputEditingState(mView, editingState); } + @Override + public void setEditableSizeAndTransform(double width, double height, double[] transform) { + saveEditableSizeAndTransform(width, height, transform); + } + @Override public void clearClient() { clearTextInputClient(); @@ -268,6 +293,7 @@ private void showTextInput(View view) { } private void hideTextInput(View view) { + notifyViewExited(); // Note: a race condition may lead to us hiding the keyboard here just after a platform view has // shown it. // This can only potentially happen when switching focus from a Flutter text field to a platform @@ -277,16 +303,51 @@ private void hideTextInput(View view) { mImm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0); } + private void notifyViewEntered() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || afm == null || !needsAutofill()) { + return; + } + + final String triggerIdentifier = configuration.autofill.uniqueIdentifier; + final int[] offset = new int[2]; + mView.getLocationOnScreen(offset); + Rect rect = new Rect(lastClientRect); + rect.offset(offset[0], offset[1]); + afm.notifyViewEntered(mView, triggerIdentifier.hashCode(), rect); + } + + private void notifyViewExited() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O + || afm == null + || configuration == null + || configuration.autofill == null) { + return; + } + + final String triggerIdentifier = configuration.autofill.uniqueIdentifier; + afm.notifyViewExited(mView, triggerIdentifier.hashCode()); + } + + private void notifyValueChanged(String newValue) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || afm == null || !needsAutofill()) { + return; + } + + final String triggerIdentifier = configuration.autofill.uniqueIdentifier; + afm.notifyValueChanged(mView, triggerIdentifier.hashCode(), AutofillValue.forText(newValue)); + } + @VisibleForTesting void setTextInputClient(int client, TextInputChannel.Configuration configuration) { inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client); - this.configuration = configuration; + updateAutofillConfigurationIfNeeded(configuration); mEditable = Editable.Factory.getInstance().newEditable(""); // setTextInputClient will be followed by a call to setTextInputEditingState. // Do a restartInput at that time. mRestartInputPending = true; unlockPlatformViewInputConnection(); + lastClientRect = null; } private void setPlatformViewTextInputClient(int platformViewId) { @@ -320,6 +381,7 @@ void setTextInputEditingState(View view, TextInputChannel.TextEditState state) { if (!state.text.equals(mEditable.toString())) { mEditable.replace(0, mEditable.length(), state.text); } + notifyValueChanged(mEditable.toString()); // Always apply state to selection which handles updating the selection if needed. applyStateToSelection(state); InputConnection connection = getLastInputConnection(); @@ -342,6 +404,141 @@ void setTextInputEditingState(View view, TextInputChannel.TextEditState state) { } } + private interface MinMax { + void inspect(double x, double y); + } + + private void saveEditableSizeAndTransform(double width, double height, double[] matrix) { + final double[] minMax = new double[4]; // minX, maxX, minY, maxY. + final boolean isAffine = matrix[3] == 0 && matrix[7] == 0 && matrix[15] == 1; + minMax[0] = minMax[1] = matrix[12] / matrix[15]; // minX and maxX. + minMax[2] = minMax[3] = matrix[13] / matrix[15]; // minY and maxY. + + final MinMax finder = + new MinMax() { + @Override + public void inspect(double x, double y) { + final double w = isAffine ? 1 : 1 / (matrix[3] * x + matrix[7] * y + matrix[15]); + final double tx = (matrix[0] * x + matrix[4] * y + matrix[12]) * w; + final double ty = (matrix[1] * x + matrix[5] * y + matrix[13]) * w; + + if (tx < minMax[0]) { + minMax[0] = tx; + } else if (tx > minMax[1]) { + minMax[1] = tx; + } + + if (ty < minMax[2]) { + minMax[2] = ty; + } else if (ty > minMax[3]) { + minMax[3] = ty; + } + } + }; + + finder.inspect(width, 0); + finder.inspect(width, height); + finder.inspect(0, height); + final Float density = mView.getContext().getResources().getDisplayMetrics().density; + lastClientRect = + new Rect( + (int) (minMax[0] * density), + (int) (minMax[2] * density), + (int) Math.ceil(minMax[1] * density), + (int) Math.ceil(minMax[3] * density)); + } + + private void updateAutofillConfigurationIfNeeded(TextInputChannel.Configuration configuration) { + notifyViewExited(); + this.configuration = configuration; + final TextInputChannel.Configuration[] configurations = configuration.fields; + + if (configuration.autofill == null) { + // Disables autofill if the configuration doesn't have an autofill field. + mAutofillConfigurations = null; + return; + } + + mAutofillConfigurations = new SparseArray<>(); + + if (configurations == null) { + mAutofillConfigurations.put( + configuration.autofill.uniqueIdentifier.hashCode(), configuration); + } else { + for (TextInputChannel.Configuration config : configurations) { + TextInputChannel.Configuration.Autofill autofill = config.autofill; + if (autofill == null) { + continue; + } + + mAutofillConfigurations.put(autofill.uniqueIdentifier.hashCode(), config); + } + } + } + + private boolean needsAutofill() { + return mAutofillConfigurations != null; + } + + public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || !needsAutofill()) { + return; + } + + final String triggerIdentifier = configuration.autofill.uniqueIdentifier; + final AutofillId parentId = structure.getAutofillId(); + for (int i = 0; i < mAutofillConfigurations.size(); i++) { + final int autofillId = mAutofillConfigurations.keyAt(i); + final TextInputChannel.Configuration config = mAutofillConfigurations.valueAt(i); + final TextInputChannel.Configuration.Autofill autofill = config.autofill; + if (autofill == null) { + continue; + } + + structure.addChildCount(1); + final ViewStructure child = structure.newChild(i); + child.setAutofillId(parentId, autofillId); + child.setAutofillValue(AutofillValue.forText(autofill.editState.text)); + child.setAutofillHints(autofill.hints); + child.setAutofillType(View.AUTOFILL_TYPE_TEXT); + child.setVisibility(View.VISIBLE); + } + } + + public void autofill(SparseArray values) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return; + } + + final TextInputChannel.Configuration.Autofill currentAutofill = configuration.autofill; + if (currentAutofill == null) { + return; + } + + final HashMap editingValues = new HashMap<>(); + for (int i = 0; i < values.size(); i++) { + int virtualId = values.keyAt(i); + + final TextInputChannel.Configuration config = mAutofillConfigurations.get(virtualId); + if (config == null || config.autofill == null) { + continue; + } + + final TextInputChannel.Configuration.Autofill autofill = config.autofill; + final String value = values.valueAt(i).getTextValue().toString(); + final TextInputChannel.TextEditState newState = + new TextInputChannel.TextEditState(value, value.length(), value.length()); + + // The value of the currently focused text field needs to be updated. + if (autofill.uniqueIdentifier.equals(currentAutofill.uniqueIdentifier)) { + setTextInputEditingState(mView, newState); + } + editingValues.put(autofill.uniqueIdentifier, newState); + } + + textInputChannel.updateEditingStateWithTag(inputTarget.id, editingValues); + } + // Samsung's Korean keyboard has a bug where it always attempts to combine characters based on // its internal state, ignoring if and when the cursor is moved programmatically. The same bug // also causes non-korean keyboards to occasionally duplicate text when tapping in the middle @@ -394,6 +591,8 @@ private void clearTextInputClient() { } inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0); unlockPlatformViewInputConnection(); + notifyViewExited(); + lastClientRect = null; } private static class InputTarget { diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index 23362b64a3499..40fcea0aceec5 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -21,15 +21,18 @@ import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.Log; +import android.util.SparseArray; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; +import android.view.ViewStructure; import android.view.WindowInsets; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeProvider; +import android.view.autofill.AutofillValue; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; @@ -445,6 +448,17 @@ public boolean checkInputConnectionProxy(View view) { .checkInputConnectionProxy(view); } + @Override + public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { + super.onProvideAutofillVirtualStructure(structure, flags); + mTextInputPlugin.onProvideAutofillVirtualStructure(structure, flags); + } + + @Override + public void autofill(SparseArray values) { + mTextInputPlugin.autofill(values); + } + @Override public boolean onTouchEvent(MotionEvent event) { if (!isAttached()) { diff --git a/shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java b/shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java index b2ecfd7b13fd6..53fb4297875e8 100644 --- a/shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java @@ -2,11 +2,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.AssetManager; @@ -15,11 +19,13 @@ import android.util.SparseIntArray; import android.view.KeyEvent; import android.view.View; +import android.view.ViewStructure; import android.view.inputmethod.CursorAnchorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.systemchannels.TextInputChannel; @@ -103,7 +109,15 @@ public void setTextInputEditingState_doesNotRestartWhenTextIsIdentical() { textInputPlugin.setTextInputClient( 0, new TextInputChannel.Configuration( - false, false, true, TextInputChannel.TextCapitalization.NONE, null, null, null)); + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + null, + null)); // There's a pending restart since we initialized the text input client. Flush that now. textInputPlugin.setTextInputEditingState( testView, new TextInputChannel.TextEditState("", 0, 0)); @@ -132,7 +146,15 @@ public void setTextInputEditingState_alwaysSetEditableWhenDifferent() { textInputPlugin.setTextInputClient( 0, new TextInputChannel.Configuration( - false, false, true, TextInputChannel.TextCapitalization.NONE, null, null, null)); + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + null, + null)); // There's a pending restart since we initialized the text input client. Flush that now. With // changed text, we should // always set the Editable contents. @@ -173,7 +195,15 @@ public void setTextInputEditingState_alwaysRestartsOnAffectedDevices2() { textInputPlugin.setTextInputClient( 0, new TextInputChannel.Configuration( - false, false, true, TextInputChannel.TextCapitalization.NONE, null, null, null)); + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + null, + null)); // There's a pending restart since we initialized the text input client. Flush that now. textInputPlugin.setTextInputEditingState( testView, new TextInputChannel.TextEditState("", 0, 0)); @@ -208,7 +238,15 @@ public void setTextInputEditingState_doesNotRestartOnUnaffectedDevices() { textInputPlugin.setTextInputClient( 0, new TextInputChannel.Configuration( - false, false, true, TextInputChannel.TextCapitalization.NONE, null, null, null)); + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + null, + null)); // There's a pending restart since we initialized the text input client. Flush that now. textInputPlugin.setTextInputEditingState( testView, new TextInputChannel.TextEditState("", 0, 0)); @@ -236,7 +274,15 @@ public void setTextInputEditingState_nullInputMethodSubtype() { textInputPlugin.setTextInputClient( 0, new TextInputChannel.Configuration( - false, false, true, TextInputChannel.TextCapitalization.NONE, null, null, null)); + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + null, + null)); // There's a pending restart since we initialized the text input client. Flush that now. textInputPlugin.setTextInputEditingState( testView, new TextInputChannel.TextEditState("", 0, 0)); @@ -262,6 +308,8 @@ public void inputConnection_createsActionFromEnter() throws JSONException { TextInputChannel.TextCapitalization.NONE, new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false), null, + null, + null, null)); // There's a pending restart since we initialized the text input client. Flush that now. textInputPlugin.setTextInputEditingState( @@ -331,6 +379,8 @@ public void inputConnection_finishComposingTextUpdatesIMM() throws JSONException TextInputChannel.TextCapitalization.NONE, new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false), null, + null, + null, null)); // There's a pending restart since we initialized the text input client. Flush that now. textInputPlugin.setTextInputEditingState( @@ -347,6 +397,116 @@ public void inputConnection_finishComposingTextUpdatesIMM() throws JSONException } } + @Test + public void autofill_onProvideVirtualViewStructure() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return; + + FlutterView testView = new FlutterView(RuntimeEnvironment.application); + TextInputPlugin textInputPlugin = + new TextInputPlugin( + testView, mock(DartExecutor.class), mock(PlatformViewsController.class)); + final TextInputChannel.Configuration.Autofill autofill1 = + new TextInputChannel.Configuration.Autofill( + "1", new String[] {"HINT1"}, new TextInputChannel.TextEditState("", 0, 0)); + final TextInputChannel.Configuration.Autofill autofill2 = + new TextInputChannel.Configuration.Autofill( + "2", new String[] {"HINT2", "EXTRA"}, new TextInputChannel.TextEditState("", 0, 0)); + + final TextInputChannel.Configuration config1 = + new TextInputChannel.Configuration( + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + autofill1, + null); + final TextInputChannel.Configuration config2 = + new TextInputChannel.Configuration( + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + autofill2, + null); + + textInputPlugin.setTextInputClient( + 0, + new TextInputChannel.Configuration( + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + autofill1, + new TextInputChannel.Configuration[] {config1, config2})); + + final ViewStructure viewStructure = mock(ViewStructure.class); + final ViewStructure[] children = {mock(ViewStructure.class), mock(ViewStructure.class)}; + + when(viewStructure.newChild(anyInt())) + .thenAnswer(invocation -> children[invocation.getArgumentAt(0, int.class)]); + + textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0); + + verify(viewStructure).newChild(0); + verify(viewStructure).newChild(1); + + verify(children[0]).setAutofillId(any(), eq("1".hashCode())); + verify(children[0]).setAutofillHints(aryEq(new String[] {"HINT1"})); + verify(children[1]).setAutofillId(any(), eq("2".hashCode())); + verify(children[1]).setAutofillHints(aryEq(new String[] {"HINT2", "EXTRA"})); + } + + @Test + public void autofill_onProvideVirtualViewStructure_single() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return; + } + + FlutterView testView = new FlutterView(RuntimeEnvironment.application); + TextInputPlugin textInputPlugin = + new TextInputPlugin( + testView, mock(DartExecutor.class), mock(PlatformViewsController.class)); + final TextInputChannel.Configuration.Autofill autofill = + new TextInputChannel.Configuration.Autofill( + "1", new String[] {"HINT1"}, new TextInputChannel.TextEditState("", 0, 0)); + + // Autofill should still work without AutofillGroup. + textInputPlugin.setTextInputClient( + 0, + new TextInputChannel.Configuration( + false, + false, + true, + TextInputChannel.TextCapitalization.NONE, + null, + null, + null, + autofill, + null)); + + final ViewStructure viewStructure = mock(ViewStructure.class); + final ViewStructure[] children = {mock(ViewStructure.class)}; + + when(viewStructure.newChild(anyInt())) + .thenAnswer(invocation -> children[invocation.getArgumentAt(0, int.class)]); + + textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0); + + verify(viewStructure).newChild(0); + + verify(children[0]).setAutofillId(any(), eq("1".hashCode())); + verify(children[0]).setAutofillHints(aryEq(new String[] {"HINT1"})); + } + @Implements(InputMethodManager.class) public static class TestImm extends ShadowInputMethodManager { private InputMethodSubtype currentInputMethodSubtype; From e64af21cae8823c58c036a8a1634e9b7880fd544 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 08:00:02 -0400 Subject: [PATCH 30/39] Roll src/third_party/skia 9ff1d841f6cc..938b4532b48f (20 commits) (#17752) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 9c22e48d2618d..30f53c365a666 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '9ff1d841f6cce901531bfba06e4ca79c50d8a696', + 'skia_revision': '938b4532b48f6749bc5453e58554bddae13a6086', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index ba4f06e609a17..d17f571e4e144 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: e1d2321667cc377404bf969087467bb9 +Signature: 3cffa92a58ccebe87459a6b8d7f7e637 UNUSED LICENSES: From d14b31d66acc853b24642603e085d6a713536f2a Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 08:50:02 -0400 Subject: [PATCH 31/39] Roll fuchsia/sdk/core/linux-amd64 from Udupa... to Pgthi... (#17754) --- DEPS | 2 +- ci/licenses_golden/licenses_fuchsia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 30f53c365a666..ed165f151dc43 100644 --- a/DEPS +++ b/DEPS @@ -554,7 +554,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'Udupac5RMB5ivSEokSjG2BTEtxphge9ZlfTuALVW8PYC' + 'version': 'PgthiSmMqgeVVi3s8ATyJ1ut411xGyk0h0lDZta1iUQC' } ], 'condition': 'host_os == "linux"', diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index e91ed62e7ab67..eff11642ccd2f 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: 2da6a5acd07c2b9887c4985c26a2708d +Signature: ce7ff857ac8a13447faa8112735366c8 UNUSED LICENSES: From e774608a5881e116e7e7d31de3e8ea39a55beb78 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 11:05:03 -0400 Subject: [PATCH 32/39] Roll fuchsia/sdk/core/mac-amd64 from urCsS... to W1XGO... (#17757) --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index ed165f151dc43..3988281dc0f65 100644 --- a/DEPS +++ b/DEPS @@ -534,7 +534,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': 'urCsSKhz2Ls7vT55uPrHLoQFUHR9DyW0bgivrJmnwmcC' + 'version': 'W1XGOOg536oZa9c08cv4pRp2Hq60gagWtr-TMSb6iN0C' } ], 'condition': 'host_os == "mac"', From 69e2b5045498c9e3d611d023add58e06d2f4c020 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 11:15:02 -0400 Subject: [PATCH 33/39] Roll src/third_party/skia 938b4532b48f..7a9c9d66f12c (2 commits) (#17758) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- sky/packages/sky_engine/LICENSE | 444 +++++++++++++++++++++++++++++++ 3 files changed, 446 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 3988281dc0f65..68c19e63e1048 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '938b4532b48f6749bc5453e58554bddae13a6086', + 'skia_revision': '7a9c9d66f12c218450e5cf64660d1a7022654cc8', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index d17f571e4e144..2315e6a072554 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 3cffa92a58ccebe87459a6b8d7f7e637 +Signature: c148ac9c08fa3116288857e0a92212cb UNUSED LICENSES: diff --git a/sky/packages/sky_engine/LICENSE b/sky/packages/sky_engine/LICENSE index 735a9fd2a6797..fca14e2785127 100644 --- a/sky/packages/sky_engine/LICENSE +++ b/sky/packages/sky_engine/LICENSE @@ -423,6 +423,7 @@ boringssl engine etc1 khronos +observatory_pub_packages txt vulkan wuffs @@ -10258,6 +10259,449 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2013, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2014, Michael Bostock and Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2014, the Dart project authors. +Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2017, the Dart project authors. +Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright 2013, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright 2015, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages + +Copyright 2016, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +observatory_pub_packages pkg Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file From 1593303df10f5992357d7c78d019eb95993a0cf9 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 12:05:02 -0400 Subject: [PATCH 34/39] Roll src/third_party/dart 983f882180cd..5900a0ac492b (10 commits) (#17759) --- DEPS | 2 +- ci/licenses_golden/licenses_third_party | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 68c19e63e1048..ef99b3b5a895c 100644 --- a/DEPS +++ b/DEPS @@ -34,7 +34,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS. # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '983f882180cdfec98b9e2dde5a0e3fb013c93ebf', + 'dart_revision': '5900a0ac492b6d8ac2ca45a63f9236c61aa3f6a9', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index feb088981aa49..b21950f8c8eb0 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: f1e6cd4d252f4c3b58ed527d376118d4 +Signature: a15387d361603f161618092ca43df1e2 UNUSED LICENSES: From 1cf1a5882d6b40cae1a7f8b7a2328ca142797220 Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Thu, 16 Apr 2020 13:40:22 -0400 Subject: [PATCH 35/39] Guard canvas virtuals so we can remove legacy didConcat44 (#17756) * Guard canvas virtuals so we can remove legacy didConcat44 SkMatrix44 is also deprecated, so start transitioning to SkM44. * Fix formatting --- shell/common/canvas_spy.cc | 4 ++++ shell/common/canvas_spy.h | 4 ++++ testing/assertions_skia.cc | 18 +++++++++--------- testing/assertions_skia.h | 3 ++- testing/mock_canvas.cc | 10 ++++++++-- testing/mock_canvas.h | 8 ++++++-- 6 files changed, 33 insertions(+), 14 deletions(-) diff --git a/shell/common/canvas_spy.cc b/shell/common/canvas_spy.cc index 5b62a34953a23..4b6301690c599 100644 --- a/shell/common/canvas_spy.cc +++ b/shell/common/canvas_spy.cc @@ -53,7 +53,11 @@ void DidDrawCanvas::willRestore() {} void DidDrawCanvas::didConcat(const SkMatrix& matrix) {} +#ifdef SK_SUPPORT_LEGACY_DIDCONCAT44 void DidDrawCanvas::didConcat44(const SkScalar[]) {} +#else +void DidDrawCanvas::didConcat44(const SkM44&) {} +#endif void DidDrawCanvas::didScale(SkScalar, SkScalar) {} diff --git a/shell/common/canvas_spy.h b/shell/common/canvas_spy.h index d5c75be34df40..594cd5224f038 100644 --- a/shell/common/canvas_spy.h +++ b/shell/common/canvas_spy.h @@ -71,7 +71,11 @@ class DidDrawCanvas final : public SkCanvasVirtualEnforcer { // |SkCanvasVirtualEnforcer| void didConcat(const SkMatrix&) override; +#ifdef SK_SUPPORT_LEGACY_DIDCONCAT44 void didConcat44(const SkScalar[]) override; +#else + void didConcat44(const SkM44&) override; +#endif void didScale(SkScalar, SkScalar) override; void didTranslate(SkScalar, SkScalar) override; diff --git a/testing/assertions_skia.cc b/testing/assertions_skia.cc index c070f1c6cc93d..d76b057bf9eb2 100644 --- a/testing/assertions_skia.cc +++ b/testing/assertions_skia.cc @@ -61,15 +61,15 @@ std::ostream& operator<<(std::ostream& os, const SkMatrix& m) { return os; } -std::ostream& operator<<(std::ostream& os, const SkMatrix44& m) { - os << m.get(0, 0) << ", " << m.get(0, 1) << ", " << m.get(0, 2) << ", " - << m.get(0, 3) << std::endl; - os << m.get(1, 0) << ", " << m.get(1, 1) << ", " << m.get(1, 2) << ", " - << m.get(1, 3) << std::endl; - os << m.get(2, 0) << ", " << m.get(2, 1) << ", " << m.get(2, 2) << ", " - << m.get(2, 3) << std::endl; - os << m.get(3, 0) << ", " << m.get(3, 1) << ", " << m.get(3, 2) << ", " - << m.get(3, 3); +std::ostream& operator<<(std::ostream& os, const SkM44& m) { + os << m.rc(0, 0) << ", " << m.rc(0, 1) << ", " << m.rc(0, 2) << ", " + << m.rc(0, 3) << std::endl; + os << m.rc(1, 0) << ", " << m.rc(1, 1) << ", " << m.rc(1, 2) << ", " + << m.rc(1, 3) << std::endl; + os << m.rc(2, 0) << ", " << m.rc(2, 1) << ", " << m.rc(2, 2) << ", " + << m.rc(2, 3) << std::endl; + os << m.rc(3, 0) << ", " << m.rc(3, 1) << ", " << m.rc(3, 2) << ", " + << m.rc(3, 3); return os; } diff --git a/testing/assertions_skia.h b/testing/assertions_skia.h index f1eec1897c426..6049e778b67eb 100644 --- a/testing/assertions_skia.h +++ b/testing/assertions_skia.h @@ -8,6 +8,7 @@ #include #include "third_party/skia/include/core/SkClipOp.h" +#include "third_party/skia/include/core/SkM44.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkMatrix44.h" #include "third_party/skia/include/core/SkPaint.h" @@ -20,7 +21,7 @@ namespace testing { extern std::ostream& operator<<(std::ostream& os, const SkClipOp& o); extern std::ostream& operator<<(std::ostream& os, const SkMatrix& m); -extern std::ostream& operator<<(std::ostream& os, const SkMatrix44& m); +extern std::ostream& operator<<(std::ostream& os, const SkM44& m); extern std::ostream& operator<<(std::ostream& os, const SkVector3& v); extern std::ostream& operator<<(std::ostream& os, const SkVector4& v); extern std::ostream& operator<<(std::ostream& os, const SkRect& r); diff --git a/testing/mock_canvas.cc b/testing/mock_canvas.cc index 300f2d4288c0d..a29d0d77e999d 100644 --- a/testing/mock_canvas.cc +++ b/testing/mock_canvas.cc @@ -60,11 +60,17 @@ void MockCanvas::didConcat(const SkMatrix& matrix) { draw_calls_.emplace_back(DrawCall{current_layer_, ConcatMatrixData{matrix}}); } +#ifdef SK_SUPPORT_LEGACY_DIDCONCAT44 void MockCanvas::didConcat44(const SkScalar matrix[]) { - SkMatrix44 m44; - m44.setColMajor(matrix); + SkM44 m44 = SkM44::ColMajor(matrix); draw_calls_.emplace_back(DrawCall{current_layer_, ConcatMatrix44Data{m44}}); } +#else +void MockCanvas::didConcat44(const SkM44& matrix) { + draw_calls_.emplace_back( + DrawCall{current_layer_, ConcatMatrix44Data{matrix}}); +} +#endif void MockCanvas::didScale(SkScalar x, SkScalar y) { SkMatrix m; diff --git a/testing/mock_canvas.h b/testing/mock_canvas.h index 2957783dbe2b5..72f5f1f9ad8c0 100644 --- a/testing/mock_canvas.h +++ b/testing/mock_canvas.h @@ -16,7 +16,7 @@ #include "third_party/skia/include/core/SkClipOp.h" #include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkImageFilter.h" -#include "third_party/skia/include/core/SkMatrix44.h" +#include "third_party/skia/include/core/SkM44.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" @@ -57,7 +57,7 @@ class MockCanvas : public SkCanvasVirtualEnforcer { }; struct ConcatMatrix44Data { - SkMatrix44 matrix; + SkM44 matrix; }; struct SetMatrixData { @@ -145,7 +145,11 @@ class MockCanvas : public SkCanvasVirtualEnforcer { void willRestore() override; void didRestore() override {} void didConcat(const SkMatrix& matrix) override; +#ifdef SK_SUPPORT_LEGACY_DIDCONCAT44 void didConcat44(const SkScalar matrix[]) override; +#else + void didConcat44(const SkM44&) override; +#endif void didScale(SkScalar x, SkScalar y) override; void didTranslate(SkScalar x, SkScalar y) override; void didSetMatrix(const SkMatrix& matrix) override; From e368377ce85777fcc015ecbcc9790984b757748e Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Thu, 16 Apr 2020 14:10:01 -0400 Subject: [PATCH 36/39] Roll src/third_party/skia 7a9c9d66f12c..efebaa2a1152 (7 commits) (#17761) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index ef99b3b5a895c..c071e16aa4a62 100644 --- a/DEPS +++ b/DEPS @@ -26,7 +26,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '7a9c9d66f12c218450e5cf64660d1a7022654cc8', + 'skia_revision': 'efebaa2a1152d3950f252d63a619f53992366ff2', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 2315e6a072554..39a234fee7b37 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: c148ac9c08fa3116288857e0a92212cb +Signature: bfea63318cfc35e64a47648bbbffcd51 UNUSED LICENSES: From ef161fb5c19ea0af8fa9a39518c595a006f23648 Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Thu, 16 Apr 2020 15:27:41 -0400 Subject: [PATCH 37/39] Convert MatrixDecomposition from SkMatrix44 to SkM44 (#17760) * Convert MatrixDecomposition from SkMatrix44 to SkM44 SkMatrix44 is deprecated and being removed. --- flow/matrix_decomposition.cc | 142 ++++++++++--------------- flow/matrix_decomposition.h | 25 +++-- flow/matrix_decomposition_unittests.cc | 120 ++++++++++----------- flow/scene_update_context.cc | 24 ++--- 4 files changed, 142 insertions(+), 169 deletions(-) diff --git a/flow/matrix_decomposition.cc b/flow/matrix_decomposition.cc index 1935393906513..c9bb1ff475da2 100644 --- a/flow/matrix_decomposition.cc +++ b/flow/matrix_decomposition.cc @@ -6,140 +6,114 @@ namespace flutter { -static inline SkVector3 SkVector3Combine(const SkVector3& a, - float a_scale, - const SkVector3& b, - float b_scale) { - return { - a_scale * a.fX + b_scale * b.fX, // - a_scale * a.fY + b_scale * b.fY, // - a_scale * a.fZ + b_scale * b.fZ, // - }; -} - -static inline SkVector3 SkVector3Cross(const SkVector3& a, const SkVector3& b) { - return { - (a.fY * b.fZ) - (a.fZ * b.fY), // - (a.fZ * b.fX) - (a.fX * b.fZ), // - (a.fX * b.fY) - (a.fY * b.fX) // - }; +static inline SkV3 SkV3Combine(const SkV3& a, + float a_scale, + const SkV3& b, + float b_scale) { + return (a * a_scale) + (b * b_scale); } MatrixDecomposition::MatrixDecomposition(const SkMatrix& matrix) - : MatrixDecomposition(SkMatrix44{matrix}) {} + : MatrixDecomposition(SkM44{matrix}) {} // Use custom normalize to avoid skia precision loss/normalize() privatization. -static inline void SkVector3Normalize(SkVector3& v) { - double mag = sqrt(v.fX * v.fX + v.fY * v.fY + v.fZ * v.fZ); +static inline void SkV3Normalize(SkV3& v) { + double mag = sqrt(v.x * v.x + v.y * v.y + v.z * v.z); double scale = 1.0 / mag; - v.fX *= scale; - v.fY *= scale; - v.fZ *= scale; + v.x *= scale; + v.y *= scale; + v.z *= scale; } -MatrixDecomposition::MatrixDecomposition(SkMatrix44 matrix) : valid_(false) { - if (matrix.get(3, 3) == 0) { +MatrixDecomposition::MatrixDecomposition(SkM44 matrix) : valid_(false) { + if (matrix.rc(3, 3) == 0) { return; } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - matrix.set(j, i, matrix.get(j, i) / matrix.get(3, 3)); + matrix.setRC(j, i, matrix.rc(j, i) / matrix.rc(3, 3)); } } - SkMatrix44 perpective_matrix = matrix; + SkM44 perpective_matrix = matrix; for (int i = 0; i < 3; i++) { - perpective_matrix.set(3, i, 0.0); + perpective_matrix.setRC(3, i, 0.0); } - perpective_matrix.set(3, 3, 1.0); + perpective_matrix.setRC(3, 3, 1.0); - if (perpective_matrix.determinant() == 0.0) { + SkM44 inverted(SkM44::Uninitialized_Constructor::kUninitialized_Constructor); + if (!perpective_matrix.invert(&inverted)) { return; } - if (matrix.get(3, 0) != 0.0 || matrix.get(3, 1) != 0.0 || - matrix.get(3, 2) != 0.0) { - const SkVector4 right_hand_side(matrix.get(3, 0), matrix.get(3, 1), - matrix.get(3, 2), matrix.get(3, 3)); - - SkMatrix44 inverted_transposed( - SkMatrix44::Uninitialized_Constructor::kUninitialized_Constructor); - if (!perpective_matrix.invert(&inverted_transposed)) { - return; - } - inverted_transposed.transpose(); + if (matrix.rc(3, 0) != 0.0 || matrix.rc(3, 1) != 0.0 || + matrix.rc(3, 2) != 0.0) { + const SkV4 right_hand_side = matrix.row(3); - perspective_ = inverted_transposed * right_hand_side; + perspective_ = inverted.transpose() * right_hand_side; - matrix.set(3, 0, 0); - matrix.set(3, 1, 0); - matrix.set(3, 2, 0); - matrix.set(3, 3, 1); + matrix.setRow(3, {0, 0, 0, 1}); } - translation_ = {matrix.get(0, 3), matrix.get(1, 3), matrix.get(2, 3)}; + translation_ = {matrix.rc(0, 3), matrix.rc(1, 3), matrix.rc(2, 3)}; - matrix.set(0, 3, 0.0); - matrix.set(1, 3, 0.0); - matrix.set(2, 3, 0.0); + matrix.setRC(0, 3, 0.0); + matrix.setRC(1, 3, 0.0); + matrix.setRC(2, 3, 0.0); - SkVector3 row[3]; + SkV3 row[3]; for (int i = 0; i < 3; i++) { - row[i].set(matrix.get(0, i), matrix.get(1, i), matrix.get(2, i)); + row[i] = {matrix.rc(0, i), matrix.rc(1, i), matrix.rc(2, i)}; } - scale_.fX = row[0].length(); + scale_.x = row[0].length(); - SkVector3Normalize(row[0]); + SkV3Normalize(row[0]); - shear_.fX = row[0].dot(row[1]); - row[1] = SkVector3Combine(row[1], 1.0, row[0], -shear_.fX); + shear_.x = row[0].dot(row[1]); + row[1] = SkV3Combine(row[1], 1.0, row[0], -shear_.x); - scale_.fY = row[1].length(); + scale_.y = row[1].length(); - SkVector3Normalize(row[1]); + SkV3Normalize(row[1]); - shear_.fX /= scale_.fY; + shear_.x /= scale_.y; - shear_.fY = row[0].dot(row[2]); - row[2] = SkVector3Combine(row[2], 1.0, row[0], -shear_.fY); - shear_.fZ = row[1].dot(row[2]); - row[2] = SkVector3Combine(row[2], 1.0, row[1], -shear_.fZ); + shear_.y = row[0].dot(row[2]); + row[2] = SkV3Combine(row[2], 1.0, row[0], -shear_.y); + shear_.z = row[1].dot(row[2]); + row[2] = SkV3Combine(row[2], 1.0, row[1], -shear_.z); - scale_.fZ = row[2].length(); + scale_.z = row[2].length(); - SkVector3Normalize(row[2]); + SkV3Normalize(row[2]); - shear_.fY /= scale_.fZ; - shear_.fZ /= scale_.fZ; + shear_.y /= scale_.z; + shear_.z /= scale_.z; - if (row[0].dot(SkVector3Cross(row[1], row[2])) < 0) { - scale_.fX *= -1; - scale_.fY *= -1; - scale_.fZ *= -1; + if (row[0].dot(row[1].cross(row[2])) < 0) { + scale_ *= -1; for (int i = 0; i < 3; i++) { - row[i].fX *= -1; - row[i].fY *= -1; - row[i].fZ *= -1; + row[i] *= -1; } } - rotation_.set(0.5 * sqrt(fmax(1.0 + row[0].fX - row[1].fY - row[2].fZ, 0.0)), - 0.5 * sqrt(fmax(1.0 - row[0].fX + row[1].fY - row[2].fZ, 0.0)), - 0.5 * sqrt(fmax(1.0 - row[0].fX - row[1].fY + row[2].fZ, 0.0)), - 0.5 * sqrt(fmax(1.0 + row[0].fX + row[1].fY + row[2].fZ, 0.0))); + rotation_.x = 0.5 * sqrt(fmax(1.0 + row[0].x - row[1].y - row[2].z, 0.0)); + rotation_.y = 0.5 * sqrt(fmax(1.0 - row[0].x + row[1].y - row[2].z, 0.0)); + rotation_.z = 0.5 * sqrt(fmax(1.0 - row[0].x - row[1].y + row[2].z, 0.0)); + rotation_.w = 0.5 * sqrt(fmax(1.0 + row[0].x + row[1].y + row[2].z, 0.0)); - if (row[2].fY > row[1].fZ) { - rotation_.fData[0] = -rotation_.fData[0]; + if (row[2].y > row[1].z) { + rotation_.x = -rotation_.x; } - if (row[0].fZ > row[2].fX) { - rotation_.fData[1] = -rotation_.fData[1]; + if (row[0].z > row[2].x) { + rotation_.y = -rotation_.y; } - if (row[1].fX > row[0].fY) { - rotation_.fData[2] = -rotation_.fData[2]; + if (row[1].x > row[0].y) { + rotation_.z = -rotation_.z; } valid_ = true; diff --git a/flow/matrix_decomposition.h b/flow/matrix_decomposition.h index 81794c2fe589f..ea0af37ae9b50 100644 --- a/flow/matrix_decomposition.h +++ b/flow/matrix_decomposition.h @@ -6,9 +6,8 @@ #define FLUTTER_FLOW_MATRIX_DECOMPOSITION_H_ #include "flutter/fml/macros.h" +#include "third_party/skia/include/core/SkM44.h" #include "third_party/skia/include/core/SkMatrix.h" -#include "third_party/skia/include/core/SkMatrix44.h" -#include "third_party/skia/include/core/SkPoint3.h" namespace flutter { @@ -19,29 +18,29 @@ class MatrixDecomposition { public: MatrixDecomposition(const SkMatrix& matrix); - MatrixDecomposition(SkMatrix44 matrix); + MatrixDecomposition(SkM44 matrix); ~MatrixDecomposition(); bool IsValid() const; - const SkVector3& translation() const { return translation_; } + const SkV3& translation() const { return translation_; } - const SkVector3& scale() const { return scale_; } + const SkV3& scale() const { return scale_; } - const SkVector3& shear() const { return shear_; } + const SkV3& shear() const { return shear_; } - const SkVector4& perspective() const { return perspective_; } + const SkV4& perspective() const { return perspective_; } - const SkVector4& rotation() const { return rotation_; } + const SkV4& rotation() const { return rotation_; } private: bool valid_; - SkVector3 translation_; - SkVector3 scale_; - SkVector3 shear_; - SkVector4 perspective_; - SkVector4 rotation_; + SkV3 translation_; + SkV3 scale_; + SkV3 shear_; + SkV4 perspective_; + SkV4 rotation_; FML_DISALLOW_COPY_AND_ASSIGN(MatrixDecomposition); }; diff --git a/flow/matrix_decomposition_unittests.cc b/flow/matrix_decomposition_unittests.cc index 8aa511e4a0a97..fb39cf0f94c85 100644 --- a/flow/matrix_decomposition_unittests.cc +++ b/flow/matrix_decomposition_unittests.cc @@ -16,24 +16,24 @@ namespace flutter { namespace testing { TEST(MatrixDecomposition, Rotation) { - SkMatrix44 matrix = SkMatrix44::I(); + SkM44 matrix; const auto angle = M_PI_4; - matrix.setRotateAbout(0.0, 0.0, 1.0, angle); + matrix.setRotate({0.0, 0.0, 1.0}, angle); flutter::MatrixDecomposition decomposition(matrix); ASSERT_TRUE(decomposition.IsValid()); const auto sine = sin(angle * 0.5); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[0]); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[1]); - ASSERT_FLOAT_EQ(sine, decomposition.rotation().fData[2]); - ASSERT_FLOAT_EQ(cos(angle * 0.5), decomposition.rotation().fData[3]); + ASSERT_FLOAT_EQ(0, decomposition.rotation().x); + ASSERT_FLOAT_EQ(0, decomposition.rotation().y); + ASSERT_FLOAT_EQ(sine, decomposition.rotation().z); + ASSERT_FLOAT_EQ(cos(angle * 0.5), decomposition.rotation().w); } TEST(MatrixDecomposition, Scale) { - SkMatrix44 matrix = SkMatrix44::I(); + SkM44 matrix; const auto scale = 5.0; matrix.setScale(scale + 0, scale + 1, scale + 2); @@ -41,13 +41,13 @@ TEST(MatrixDecomposition, Scale) { flutter::MatrixDecomposition decomposition(matrix); ASSERT_TRUE(decomposition.IsValid()); - ASSERT_FLOAT_EQ(scale + 0, decomposition.scale().fX); - ASSERT_FLOAT_EQ(scale + 1, decomposition.scale().fY); - ASSERT_FLOAT_EQ(scale + 2, decomposition.scale().fZ); + ASSERT_FLOAT_EQ(scale + 0, decomposition.scale().x); + ASSERT_FLOAT_EQ(scale + 1, decomposition.scale().y); + ASSERT_FLOAT_EQ(scale + 2, decomposition.scale().z); } TEST(MatrixDecomposition, Translate) { - SkMatrix44 matrix = SkMatrix44::I(); + SkM44 matrix; const auto translate = 125.0; matrix.setTranslate(translate + 0, translate + 1, translate + 2); @@ -55,9 +55,9 @@ TEST(MatrixDecomposition, Translate) { flutter::MatrixDecomposition decomposition(matrix); ASSERT_TRUE(decomposition.IsValid()); - ASSERT_FLOAT_EQ(translate + 0, decomposition.translation().fX); - ASSERT_FLOAT_EQ(translate + 1, decomposition.translation().fY); - ASSERT_FLOAT_EQ(translate + 2, decomposition.translation().fZ); + ASSERT_FLOAT_EQ(translate + 0, decomposition.translation().x); + ASSERT_FLOAT_EQ(translate + 1, decomposition.translation().y); + ASSERT_FLOAT_EQ(translate + 2, decomposition.translation().z); } TEST(MatrixDecomposition, Combination) { @@ -65,65 +65,65 @@ TEST(MatrixDecomposition, Combination) { const auto scale = 5; const auto translate = 125.0; - SkMatrix44 m1 = SkMatrix44::I(); - m1.setRotateAbout(0, 0, 1, rotation); + SkM44 m1; + m1.setRotate({0, 0, 1}, rotation); - SkMatrix44 m2 = SkMatrix44::I(); - m2.setScale(scale); + SkM44 m2; + m2.setScale(scale, scale, scale); - SkMatrix44 m3 = SkMatrix44::I(); + SkM44 m3; m3.setTranslate(translate, translate, translate); - SkMatrix44 combined = m3 * m2 * m1; + SkM44 combined = m3 * m2 * m1; flutter::MatrixDecomposition decomposition(combined); ASSERT_TRUE(decomposition.IsValid()); - ASSERT_FLOAT_EQ(translate, decomposition.translation().fX); - ASSERT_FLOAT_EQ(translate, decomposition.translation().fY); - ASSERT_FLOAT_EQ(translate, decomposition.translation().fZ); + ASSERT_FLOAT_EQ(translate, decomposition.translation().x); + ASSERT_FLOAT_EQ(translate, decomposition.translation().y); + ASSERT_FLOAT_EQ(translate, decomposition.translation().z); - ASSERT_FLOAT_EQ(scale, decomposition.scale().fX); - ASSERT_FLOAT_EQ(scale, decomposition.scale().fY); - ASSERT_FLOAT_EQ(scale, decomposition.scale().fZ); + ASSERT_FLOAT_EQ(scale, decomposition.scale().x); + ASSERT_FLOAT_EQ(scale, decomposition.scale().y); + ASSERT_FLOAT_EQ(scale, decomposition.scale().z); const auto sine = sin(rotation * 0.5); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[0]); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[1]); - ASSERT_FLOAT_EQ(sine, decomposition.rotation().fData[2]); - ASSERT_FLOAT_EQ(cos(rotation * 0.5), decomposition.rotation().fData[3]); + ASSERT_FLOAT_EQ(0, decomposition.rotation().x); + ASSERT_FLOAT_EQ(0, decomposition.rotation().y); + ASSERT_FLOAT_EQ(sine, decomposition.rotation().z); + ASSERT_FLOAT_EQ(cos(rotation * 0.5), decomposition.rotation().w); } TEST(MatrixDecomposition, ScaleFloatError) { constexpr float scale_increment = 0.00001f; for (float scale = 0.0001f; scale < 2.0f; scale += scale_increment) { - SkMatrix44 matrix = SkMatrix44::I(); + SkM44 matrix; matrix.setScale(scale, scale, 1.0f); flutter::MatrixDecomposition decomposition3(matrix); ASSERT_TRUE(decomposition3.IsValid()); - ASSERT_FLOAT_EQ(scale, decomposition3.scale().fX); - ASSERT_FLOAT_EQ(scale, decomposition3.scale().fY); - ASSERT_FLOAT_EQ(1.f, decomposition3.scale().fZ); - ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[0]); - ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[1]); - ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[2]); + ASSERT_FLOAT_EQ(scale, decomposition3.scale().x); + ASSERT_FLOAT_EQ(scale, decomposition3.scale().y); + ASSERT_FLOAT_EQ(1.f, decomposition3.scale().z); + ASSERT_FLOAT_EQ(0, decomposition3.rotation().x); + ASSERT_FLOAT_EQ(0, decomposition3.rotation().y); + ASSERT_FLOAT_EQ(0, decomposition3.rotation().z); } - SkMatrix44 matrix = SkMatrix44::I(); + SkM44 matrix; const auto scale = 1.7734375f; matrix.setScale(scale, scale, 1.f); // Bug upper bound (empirical) const auto scale2 = 1.773437559603f; - SkMatrix44 matrix2 = SkMatrix44::I(); + SkM44 matrix2; matrix2.setScale(scale2, scale2, 1.f); // Bug lower bound (empirical) const auto scale3 = 1.7734374403954f; - SkMatrix44 matrix3 = SkMatrix44::I(); + SkM44 matrix3; matrix3.setScale(scale3, scale3, 1.f); flutter::MatrixDecomposition decomposition(matrix); @@ -135,26 +135,26 @@ TEST(MatrixDecomposition, ScaleFloatError) { flutter::MatrixDecomposition decomposition3(matrix3); ASSERT_TRUE(decomposition3.IsValid()); - ASSERT_FLOAT_EQ(scale, decomposition.scale().fX); - ASSERT_FLOAT_EQ(scale, decomposition.scale().fY); - ASSERT_FLOAT_EQ(1.f, decomposition.scale().fZ); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[0]); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[1]); - ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[2]); - - ASSERT_FLOAT_EQ(scale2, decomposition2.scale().fX); - ASSERT_FLOAT_EQ(scale2, decomposition2.scale().fY); - ASSERT_FLOAT_EQ(1.f, decomposition2.scale().fZ); - ASSERT_FLOAT_EQ(0, decomposition2.rotation().fData[0]); - ASSERT_FLOAT_EQ(0, decomposition2.rotation().fData[1]); - ASSERT_FLOAT_EQ(0, decomposition2.rotation().fData[2]); - - ASSERT_FLOAT_EQ(scale3, decomposition3.scale().fX); - ASSERT_FLOAT_EQ(scale3, decomposition3.scale().fY); - ASSERT_FLOAT_EQ(1.f, decomposition3.scale().fZ); - ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[0]); - ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[1]); - ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[2]); + ASSERT_FLOAT_EQ(scale, decomposition.scale().x); + ASSERT_FLOAT_EQ(scale, decomposition.scale().y); + ASSERT_FLOAT_EQ(1.f, decomposition.scale().z); + ASSERT_FLOAT_EQ(0, decomposition.rotation().x); + ASSERT_FLOAT_EQ(0, decomposition.rotation().y); + ASSERT_FLOAT_EQ(0, decomposition.rotation().z); + + ASSERT_FLOAT_EQ(scale2, decomposition2.scale().x); + ASSERT_FLOAT_EQ(scale2, decomposition2.scale().y); + ASSERT_FLOAT_EQ(1.f, decomposition2.scale().z); + ASSERT_FLOAT_EQ(0, decomposition2.rotation().x); + ASSERT_FLOAT_EQ(0, decomposition2.rotation().y); + ASSERT_FLOAT_EQ(0, decomposition2.rotation().z); + + ASSERT_FLOAT_EQ(scale3, decomposition3.scale().x); + ASSERT_FLOAT_EQ(scale3, decomposition3.scale().y); + ASSERT_FLOAT_EQ(1.f, decomposition3.scale().z); + ASSERT_FLOAT_EQ(0, decomposition3.rotation().x); + ASSERT_FLOAT_EQ(0, decomposition3.rotation().y); + ASSERT_FLOAT_EQ(0, decomposition3.rotation().z); } } // namespace testing diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index 1dadfd7327f23..bca3debe05e70 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -250,22 +250,22 @@ SceneUpdateContext::Transform::Transform(SceneUpdateContext& context, if (decomposition.IsValid()) { // Don't allow clients to control the z dimension; we control that // instead to make sure layers appear in proper order. - entity_node().SetTranslation(decomposition.translation().x(), // - decomposition.translation().y(), // - 0.f // + entity_node().SetTranslation(decomposition.translation().x, // + decomposition.translation().y, // + 0.f // ); - entity_node().SetScale(decomposition.scale().x(), // - decomposition.scale().y(), // - 1.f // + entity_node().SetScale(decomposition.scale().x, // + decomposition.scale().y, // + 1.f // ); - context.top_scale_x_ *= decomposition.scale().x(); - context.top_scale_y_ *= decomposition.scale().y(); + context.top_scale_x_ *= decomposition.scale().x; + context.top_scale_y_ *= decomposition.scale().y; - entity_node().SetRotation(decomposition.rotation().fData[0], // - decomposition.rotation().fData[1], // - decomposition.rotation().fData[2], // - decomposition.rotation().fData[3] // + entity_node().SetRotation(decomposition.rotation().x, // + decomposition.rotation().y, // + decomposition.rotation().z, // + decomposition.rotation().w // ); } } From f4d6ce13dcc464b0945bb641620a29f17c989a76 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 16 Apr 2020 13:23:05 -0700 Subject: [PATCH 38/39] Clear focus if a platform view goes away (#17381) --- .../io/flutter/view/AccessibilityBridge.java | 41 ++++- .../view/AccessibilityViewEmbedder.java | 14 +- .../flutter/view/AccessibilityBridgeTest.java | 140 +++++++++++++++--- 3 files changed, 173 insertions(+), 22 deletions(-) diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index bd01f405ab213..fa1050e0c7f96 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -26,6 +26,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import androidx.annotation.VisibleForTesting; import io.flutter.BuildConfig; import io.flutter.embedding.engine.systemchannels.AccessibilityChannel; import io.flutter.plugin.platform.PlatformViewsAccessibilityDelegate; @@ -333,10 +334,32 @@ public AccessibilityBridge( // TODO(mattcarrol): Add the annotation once the plumbing is done. // https://github.com/flutter/flutter/issues/29618 PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate) { + this( + rootAccessibilityView, + accessibilityChannel, + accessibilityManager, + contentResolver, + new AccessibilityViewEmbedder(rootAccessibilityView, MIN_ENGINE_GENERATED_NODE_ID), + platformViewsAccessibilityDelegate); + } + + @VisibleForTesting + public AccessibilityBridge( + @NonNull View rootAccessibilityView, + @NonNull AccessibilityChannel accessibilityChannel, + @NonNull AccessibilityManager accessibilityManager, + @NonNull ContentResolver contentResolver, + @NonNull AccessibilityViewEmbedder accessibilityViewEmbedder, + // This should be @NonNull once the plumbing for + // io.flutter.embedding.engine.android.FlutterView is done. + // TODO(mattcarrol): Add the annotation once the plumbing is done. + // https://github.com/flutter/flutter/issues/29618 + PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate) { this.rootAccessibilityView = rootAccessibilityView; this.accessibilityChannel = accessibilityChannel; this.accessibilityManager = accessibilityManager; this.contentResolver = contentResolver; + this.accessibilityViewEmbedder = accessibilityViewEmbedder; this.platformViewsAccessibilityDelegate = platformViewsAccessibilityDelegate; // Tell Flutter whether accessibility is initially active or not. Then register a listener @@ -388,8 +411,6 @@ public void onTouchExplorationStateChanged(boolean isTouchExplorationEnabled) { if (platformViewsAccessibilityDelegate != null) { platformViewsAccessibilityDelegate.attachAccessibilityBridge(this); } - accessibilityViewEmbedder = - new AccessibilityViewEmbedder(rootAccessibilityView, MIN_ENGINE_GENERATED_NODE_ID); } /** @@ -1580,15 +1601,31 @@ private void willRemoveSemanticsNode(SemanticsNode semanticsNodeToBeRemoved) { // for null'ing accessibilityFocusedSemanticsNode, inputFocusedSemanticsNode, // and hoveredObject. Is this a hook method or a command? semanticsNodeToBeRemoved.parent = null; + + if (semanticsNodeToBeRemoved.platformViewId != -1 + && embeddedAccessibilityFocusedNodeId != null + && accessibilityViewEmbedder.platformViewOfNode(embeddedAccessibilityFocusedNodeId) + == platformViewsAccessibilityDelegate.getPlatformViewById( + semanticsNodeToBeRemoved.platformViewId)) { + // If the currently focused a11y node is within a platform view that is + // getting removed: clear it's a11y focus. + sendAccessibilityEvent( + embeddedAccessibilityFocusedNodeId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + embeddedAccessibilityFocusedNodeId = null; + } + if (accessibilityFocusedSemanticsNode == semanticsNodeToBeRemoved) { sendAccessibilityEvent( accessibilityFocusedSemanticsNode.id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); accessibilityFocusedSemanticsNode = null; } + if (inputFocusedSemanticsNode == semanticsNodeToBeRemoved) { inputFocusedSemanticsNode = null; } + if (hoveredObject == semanticsNodeToBeRemoved) { hoveredObject = null; } diff --git a/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java b/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java index 0fb2957d92410..2823eb795d17b 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java +++ b/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java @@ -44,7 +44,7 @@ * corresponding platform view and `originId`. */ @Keep -final class AccessibilityViewEmbedder { +class AccessibilityViewEmbedder { private static final String TAG = "AccessibilityBridge"; private final ReflectionAccessors reflectionAccessors; @@ -387,6 +387,18 @@ public boolean onAccessibilityHoverEvent(int rootFlutterId, @NonNull MotionEvent return origin.view.dispatchGenericMotionEvent(translatedEvent); } + /** + * Returns the View that contains the accessibility node identified by the provided flutterId or + * null if it doesn't belong to a view. + */ + public View platformViewOfNode(int flutterId) { + ViewAndId viewAndId = flutterIdToOrigin.get(flutterId); + if (viewAndId == null) { + return null; + } + return viewAndId.view; + } + private static class ViewAndId { final View view; final int id; diff --git a/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java b/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java index aef458733d7b7..5bbc7b999a7dd 100644 --- a/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java +++ b/shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java @@ -5,20 +5,27 @@ package io.flutter.view; import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; import android.view.View; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import io.flutter.embedding.engine.systemchannels.AccessibilityChannel; import io.flutter.plugin.platform.PlatformViewsAccessibilityDelegate; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @@ -73,24 +80,103 @@ public void itDoesNotContainADescriptionIfScopesRoute() { assertEquals(nodeInfo.getText(), null); } - AccessibilityBridge setUpBridge() { - View view = mock(View.class); + @Test + public void itUnfocusesPlatformViewWhenPlatformViewGoesAway() { + AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class); + AccessibilityManager mockManager = mock(AccessibilityManager.class); + View mockRootView = mock(View.class); Context context = mock(Context.class); - when(view.getContext()).thenReturn(context); + when(mockRootView.getContext()).thenReturn(context); when(context.getPackageName()).thenReturn("test"); - AccessibilityChannel accessibilityChannel = mock(AccessibilityChannel.class); - AccessibilityManager accessibilityManager = mock(AccessibilityManager.class); - ContentResolver contentResolver = mock(ContentResolver.class); - PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate = - mock(PlatformViewsAccessibilityDelegate.class); AccessibilityBridge accessibilityBridge = - new AccessibilityBridge( - view, - accessibilityChannel, - accessibilityManager, - contentResolver, - platformViewsAccessibilityDelegate); - return accessibilityBridge; + setUpBridge(mockRootView, mockManager, mockViewEmbedder); + + // Sent a11y tree with platform view. + TestSemanticsNode root = new TestSemanticsNode(); + root.id = 0; + TestSemanticsNode platformView = new TestSemanticsNode(); + platformView.id = 1; + platformView.platformViewId = 42; + root.children.add(platformView); + TestSemanticsUpdate testSemanticsUpdate = root.toUpdate(); + accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings); + + // Set a11y focus to platform view. + View mockView = mock(View.class); + AccessibilityEvent focusEvent = mock(AccessibilityEvent.class); + when(mockViewEmbedder.requestSendAccessibilityEvent(mockView, mockView, focusEvent)) + .thenReturn(true); + when(mockViewEmbedder.getRecordFlutterId(mockView, focusEvent)).thenReturn(42); + when(focusEvent.getEventType()).thenReturn(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + accessibilityBridge.externalViewRequestSendAccessibilityEvent(mockView, mockView, focusEvent); + + // Replace the platform view. + TestSemanticsNode node = new TestSemanticsNode(); + node.id = 2; + root.children.clear(); + root.children.add(node); + testSemanticsUpdate = root.toUpdate(); + when(mockManager.isEnabled()).thenReturn(true); + ViewParent mockParent = mock(ViewParent.class); + when(mockRootView.getParent()).thenReturn(mockParent); + accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings); + + // Check that unfocus event was sent. + ArgumentCaptor eventCaptor = + ArgumentCaptor.forClass(AccessibilityEvent.class); + verify(mockParent, times(2)) + .requestSendAccessibilityEvent(eq(mockRootView), eventCaptor.capture()); + AccessibilityEvent event = eventCaptor.getAllValues().get(0); + assertEquals(event.getEventType(), AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + } + + AccessibilityBridge setUpBridge() { + return setUpBridge(null, null, null, null, null, null); + } + + AccessibilityBridge setUpBridge( + View rootAccessibilityView, + AccessibilityManager accessibilityManager, + AccessibilityViewEmbedder accessibilityViewEmbedder) { + return setUpBridge( + rootAccessibilityView, null, accessibilityManager, null, accessibilityViewEmbedder, null); + } + + AccessibilityBridge setUpBridge( + View rootAccessibilityView, + AccessibilityChannel accessibilityChannel, + AccessibilityManager accessibilityManager, + ContentResolver contentResolver, + AccessibilityViewEmbedder accessibilityViewEmbedder, + PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate) { + if (rootAccessibilityView == null) { + rootAccessibilityView = mock(View.class); + Context context = mock(Context.class); + when(rootAccessibilityView.getContext()).thenReturn(context); + when(context.getPackageName()).thenReturn("test"); + } + if (accessibilityChannel == null) { + accessibilityChannel = mock(AccessibilityChannel.class); + } + if (accessibilityManager == null) { + accessibilityManager = mock(AccessibilityManager.class); + } + if (contentResolver == null) { + contentResolver = mock(ContentResolver.class); + } + if (accessibilityViewEmbedder == null) { + accessibilityViewEmbedder = mock(AccessibilityViewEmbedder.class); + } + if (platformViewsAccessibilityDelegate == null) { + platformViewsAccessibilityDelegate = mock(PlatformViewsAccessibilityDelegate.class); + } + return new AccessibilityBridge( + rootAccessibilityView, + accessibilityChannel, + accessibilityManager, + contentResolver, + accessibilityViewEmbedder, + platformViewsAccessibilityDelegate); } /// The encoding for semantics is described in platform_view_android.cc @@ -136,11 +222,18 @@ void addFlag(AccessibilityBridge.Flag flag) { float top = 0.0f; float right = 0.0f; float bottom = 0.0f; - // children and custom actions not supported. + final List children = new ArrayList(); + // custom actions not supported. TestSemanticsUpdate toUpdate() { ArrayList strings = new ArrayList(); ByteBuffer bytes = ByteBuffer.allocate(1000); + addToBuffer(bytes, strings); + bytes.flip(); + return new TestSemanticsUpdate(bytes, strings.toArray(new String[strings.size()])); + } + + protected void addToBuffer(ByteBuffer bytes, ArrayList strings) { bytes.putInt(id); bytes.putInt(flags); bytes.putInt(actions); @@ -169,11 +262,20 @@ TestSemanticsUpdate toUpdate() { bytes.putFloat(0); } // children in traversal order. - bytes.putInt(0); + bytes.putInt(children.size()); + for (TestSemanticsNode node : children) { + bytes.putInt(node.id); + } + // children in hit test order. + for (TestSemanticsNode node : children) { + bytes.putInt(node.id); + } // custom actions bytes.putInt(0); - bytes.flip(); - return new TestSemanticsUpdate(bytes, strings.toArray(new String[strings.size()])); + // child nodes + for (TestSemanticsNode node : children) { + node.addToBuffer(bytes, strings); + } } } From 99f8d007aaefcf2cb0a0a40c0b3c6a6fd7556f5c Mon Sep 17 00:00:00 2001 From: liyuqian Date: Thu, 16 Apr 2020 15:41:07 -0700 Subject: [PATCH 39/39] Remove layer integral offset snapping (#17712) This fixes https://github.com/flutter/flutter/issues/53288 and https://github.com/flutter/flutter/issues/41654. It removes the problematic `GetIntegralTransCTM`, but preserves the rect round-out in `RasterCacheResult::draw` for performance considerations: the average frame raster time doesn't change much but the worst frame raster time significantly regressed if rect round-out is removed. That's probably because a new shader needs to be compiled to draw raster cache with fractional offsets. --- flow/layers/image_filter_layer.cc | 9 --- flow/layers/image_filter_layer_unittests.cc | 68 ++++++++------------- flow/layers/opacity_layer.cc | 11 +--- flow/layers/opacity_layer_unittests.cc | 39 ------------ flow/layers/picture_layer.cc | 7 --- flow/layers/picture_layer_unittests.cc | 19 ++---- flow/raster_cache.h | 7 --- flow/raster_cache_key.h | 7 +-- 8 files changed, 33 insertions(+), 134 deletions(-) diff --git a/flow/layers/image_filter_layer.cc b/flow/layers/image_filter_layer.cc index 212c396b6efbf..4df19eb66416b 100644 --- a/flow/layers/image_filter_layer.cc +++ b/flow/layers/image_filter_layer.cc @@ -31,9 +31,6 @@ void ImageFilterLayer::Preroll(PrerollContext* context, if (!context->has_platform_view && context->raster_cache && SkRect::Intersects(context->cull_rect, paint_bounds())) { SkMatrix ctm = matrix; -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - ctm = RasterCache::GetIntegralTransCTM(ctm); -#endif context->raster_cache->Prepare(context, this, ctm); } } @@ -42,12 +39,6 @@ void ImageFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ImageFilterLayer::Paint"); FML_DCHECK(needs_painting()); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - SkAutoCanvasRestore save(context.leaf_nodes_canvas, true); - context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM( - context.leaf_nodes_canvas->getTotalMatrix())); -#endif - if (context.raster_cache) { const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); RasterCacheResult layer_cache = diff --git a/flow/layers/image_filter_layer_unittests.cc b/flow/layers/image_filter_layer_unittests.cc index f4f621a529a08..305ec01611068 100644 --- a/flow/layers/image_filter_layer_unittests.cc +++ b/flow/layers/image_filter_layer_unittests.cc @@ -60,14 +60,11 @@ TEST_F(ImageFilterLayerTest, EmptyFilter) { layer->Paint(paint_context()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector({ - MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}}, MockCanvas::DrawCall{ - 1, MockCanvas::SaveLayerData{child_bounds, filter_paint, - nullptr, 2}}, + 0, MockCanvas::SaveLayerData{child_bounds, filter_paint, + nullptr, 1}}, MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path, child_paint}}, - MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, + 1, MockCanvas::DrawPathData{child_path, child_paint}}, MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, })); } @@ -96,14 +93,11 @@ TEST_F(ImageFilterLayerTest, SimpleFilter) { layer->Paint(paint_context()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector({ - MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}}, MockCanvas::DrawCall{ - 1, MockCanvas::SaveLayerData{child_bounds, filter_paint, - nullptr, 2}}, + 0, MockCanvas::SaveLayerData{child_bounds, filter_paint, + nullptr, 1}}, MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path, child_paint}}, - MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, + 1, MockCanvas::DrawPathData{child_path, child_paint}}, MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, })); } @@ -132,14 +126,11 @@ TEST_F(ImageFilterLayerTest, SimpleFilterBounds) { layer->Paint(paint_context()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector({ - MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}}, MockCanvas::DrawCall{ - 1, MockCanvas::SaveLayerData{child_bounds, filter_paint, - nullptr, 2}}, + 0, MockCanvas::SaveLayerData{child_bounds, filter_paint, + nullptr, 1}}, MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path, child_paint}}, - MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, + 1, MockCanvas::DrawPathData{child_path, child_paint}}, MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, })); } @@ -177,19 +168,16 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) { SkPaint filter_paint; filter_paint.setImageFilter(layer_filter); layer->Paint(paint_context()); - EXPECT_EQ(mock_canvas().draw_calls(), - std::vector( - {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}}, - MockCanvas::DrawCall{ - 1, MockCanvas::SaveLayerData{children_bounds, filter_paint, - nullptr, 2}}, - MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path1, child_paint1}}, - MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path2, child_paint2}}, - MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}})); + EXPECT_EQ( + mock_canvas().draw_calls(), + std::vector({MockCanvas::DrawCall{ + 0, MockCanvas::SaveLayerData{children_bounds, + filter_paint, nullptr, 1}}, + MockCanvas::DrawCall{ + 1, MockCanvas::DrawPathData{child_path1, child_paint1}}, + MockCanvas::DrawCall{ + 1, MockCanvas::DrawPathData{child_path2, child_paint2}}, + MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}})); } TEST_F(ImageFilterLayerTest, Nested) { @@ -237,22 +225,16 @@ TEST_F(ImageFilterLayerTest, Nested) { layer1->Paint(paint_context()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector({ - MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}}, MockCanvas::DrawCall{ - 1, MockCanvas::SaveLayerData{children_bounds, filter_paint1, - nullptr, 2}}, + 0, MockCanvas::SaveLayerData{children_bounds, filter_paint1, + nullptr, 1}}, MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path1, child_paint1}}, - MockCanvas::DrawCall{2, MockCanvas::SaveData{3}}, - MockCanvas::DrawCall{3, MockCanvas::SetMatrixData{SkMatrix()}}, + 1, MockCanvas::DrawPathData{child_path1, child_paint1}}, MockCanvas::DrawCall{ - 3, MockCanvas::SaveLayerData{child_path2.getBounds(), - filter_paint2, nullptr, 4}}, + 1, MockCanvas::SaveLayerData{child_path2.getBounds(), + filter_paint2, nullptr, 2}}, MockCanvas::DrawCall{ - 4, MockCanvas::DrawPathData{child_path2, child_paint2}}, - MockCanvas::DrawCall{4, MockCanvas::RestoreData{3}}, - MockCanvas::DrawCall{3, MockCanvas::RestoreData{2}}, + 2, MockCanvas::DrawPathData{child_path2, child_paint2}}, MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, })); diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index 7899c31784b89..51fcc6c507fcb 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -51,9 +51,6 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { if (!context->has_platform_view && context->raster_cache && SkRect::Intersects(context->cull_rect, paint_bounds())) { SkMatrix ctm = child_matrix; -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - ctm = RasterCache::GetIntegralTransCTM(ctm); -#endif context->raster_cache->Prepare(context, container, ctm); } } @@ -69,11 +66,6 @@ void OpacityLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->translate(offset_.fX, offset_.fY); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - context.internal_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM( - context.leaf_nodes_canvas->getTotalMatrix())); -#endif - if (context.raster_cache) { ContainerLayer* container = GetChildContainer(); const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); @@ -87,8 +79,7 @@ void OpacityLayer::Paint(PaintContext& context) const { // Skia may clip the content with saveLayerBounds (although it's not a // guaranteed clip). So we have to provide a big enough saveLayerBounds. To do // so, we first remove the offset from paint bounds since it's already in the - // matrix. Then we round out the bounds because of our - // RasterCache::GetIntegralTransCTM optimization. + // matrix. Then we round out the bounds. // // Note that the following lines are only accessible when the raster cache is // not available (e.g., when we're using the software backend in golden diff --git a/flow/layers/opacity_layer_unittests.cc b/flow/layers/opacity_layer_unittests.cc index f7cc77ffe2ddd..ae08109fa25cf 100644 --- a/flow/layers/opacity_layer_unittests.cc +++ b/flow/layers/opacity_layer_unittests.cc @@ -58,10 +58,6 @@ TEST_F(OpacityLayerTest, FullyOpaque) { const SkMatrix initial_transform = SkMatrix::MakeTrans(0.5f, 0.5f); const SkMatrix layer_transform = SkMatrix::MakeTrans(layer_offset.fX, layer_offset.fY); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - const SkMatrix integral_layer_transform = RasterCache::GetIntegralTransCTM( - SkMatrix::Concat(initial_transform, layer_transform)); -#endif const SkPaint child_paint = SkPaint(SkColors::kGreen); const SkRect expected_layer_bounds = layer_transform.mapRect(child_path.getBounds()); @@ -86,10 +82,6 @@ TEST_F(OpacityLayerTest, FullyOpaque) { auto expected_draw_calls = std::vector( {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer_transform}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 1, MockCanvas::SetMatrixData{integral_layer_transform}}, -#endif MockCanvas::DrawCall{ 1, MockCanvas::SaveLayerData{opacity_bounds, opacity_paint, nullptr, 2}}, @@ -107,10 +99,6 @@ TEST_F(OpacityLayerTest, FullyTransparent) { const SkMatrix initial_transform = SkMatrix::MakeTrans(0.5f, 0.5f); const SkMatrix layer_transform = SkMatrix::MakeTrans(layer_offset.fX, layer_offset.fY); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - const SkMatrix integral_layer_transform = RasterCache::GetIntegralTransCTM( - SkMatrix::Concat(initial_transform, layer_transform)); -#endif const SkPaint child_paint = SkPaint(SkColors::kGreen); const SkRect expected_layer_bounds = layer_transform.mapRect(child_path.getBounds()); @@ -133,10 +121,6 @@ TEST_F(OpacityLayerTest, FullyTransparent) { auto expected_draw_calls = std::vector( {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer_transform}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 1, MockCanvas::SetMatrixData{integral_layer_transform}}, -#endif MockCanvas::DrawCall{1, MockCanvas::SaveData{2}}, MockCanvas::DrawCall{ 2, MockCanvas::ClipRectData{kEmptyRect, SkClipOp::kIntersect, @@ -155,10 +139,6 @@ TEST_F(OpacityLayerTest, HalfTransparent) { const SkMatrix initial_transform = SkMatrix::MakeTrans(0.5f, 0.5f); const SkMatrix layer_transform = SkMatrix::MakeTrans(layer_offset.fX, layer_offset.fY); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - const SkMatrix integral_layer_transform = RasterCache::GetIntegralTransCTM( - SkMatrix::Concat(initial_transform, layer_transform)); -#endif const SkPaint child_paint = SkPaint(SkColors::kGreen); const SkRect expected_layer_bounds = layer_transform.mapRect(child_path.getBounds()); @@ -185,10 +165,6 @@ TEST_F(OpacityLayerTest, HalfTransparent) { auto expected_draw_calls = std::vector( {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer_transform}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 1, MockCanvas::SetMatrixData{integral_layer_transform}}, -#endif MockCanvas::DrawCall{ 1, MockCanvas::SaveLayerData{opacity_bounds, opacity_paint, nullptr, 2}}, @@ -211,13 +187,6 @@ TEST_F(OpacityLayerTest, Nested) { SkMatrix::MakeTrans(layer1_offset.fX, layer1_offset.fY); const SkMatrix layer2_transform = SkMatrix::MakeTrans(layer2_offset.fX, layer2_offset.fY); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - const SkMatrix integral_layer1_transform = RasterCache::GetIntegralTransCTM( - SkMatrix::Concat(initial_transform, layer1_transform)); - const SkMatrix integral_layer2_transform = RasterCache::GetIntegralTransCTM( - SkMatrix::Concat(SkMatrix::Concat(initial_transform, layer1_transform), - layer2_transform)); -#endif const SkPaint child1_paint = SkPaint(SkColors::kRed); const SkPaint child2_paint = SkPaint(SkColors::kBlue); const SkPaint child3_paint = SkPaint(SkColors::kGreen); @@ -278,10 +247,6 @@ TEST_F(OpacityLayerTest, Nested) { auto expected_draw_calls = std::vector( {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer1_transform}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 1, MockCanvas::SetMatrixData{integral_layer1_transform}}, -#endif MockCanvas::DrawCall{ 1, MockCanvas::SaveLayerData{opacity1_bounds, opacity1_paint, nullptr, 2}}, @@ -289,10 +254,6 @@ TEST_F(OpacityLayerTest, Nested) { 2, MockCanvas::DrawPathData{child1_path, child1_paint}}, MockCanvas::DrawCall{2, MockCanvas::SaveData{3}}, MockCanvas::DrawCall{3, MockCanvas::ConcatMatrixData{layer2_transform}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 3, MockCanvas::SetMatrixData{integral_layer2_transform}}, -#endif MockCanvas::DrawCall{ 3, MockCanvas::SaveLayerData{opacity2_bounds, opacity2_paint, nullptr, 4}}, diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 08c09cc9e833b..5a615168b1de5 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -26,9 +26,6 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkMatrix ctm = matrix; ctm.postTranslate(offset_.x(), offset_.y()); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - ctm = RasterCache::GetIntegralTransCTM(ctm); -#endif cache->Prepare(context->gr_context, sk_picture, ctm, context->dst_color_space, is_complex_, will_change_); } @@ -44,10 +41,6 @@ void PictureLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.leaf_nodes_canvas, true); context.leaf_nodes_canvas->translate(offset_.x(), offset_.y()); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM( - context.leaf_nodes_canvas->getTotalMatrix())); -#endif if (context.raster_cache) { const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); diff --git a/flow/layers/picture_layer_unittests.cc b/flow/layers/picture_layer_unittests.cc index 4f565cf500ecc..0cdb2f94f4542 100644 --- a/flow/layers/picture_layer_unittests.cc +++ b/flow/layers/picture_layer_unittests.cc @@ -11,10 +11,6 @@ #include "flutter/testing/mock_canvas.h" #include "third_party/skia/include/core/SkPicture.h" -#ifndef SUPPORT_FRACTIONAL_TRANSLATION -#include "flutter/flow/raster_cache.h" -#endif - namespace flutter { namespace testing { @@ -85,16 +81,11 @@ TEST_F(PictureLayerTest, SimplePicture) { EXPECT_FALSE(layer->needs_system_composite()); layer->Paint(paint_context()); - auto expected_draw_calls = std::vector( - {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, - MockCanvas::DrawCall{1, - MockCanvas::ConcatMatrixData{layer_offset_matrix}}, -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - MockCanvas::DrawCall{ - 1, MockCanvas::SetMatrixData{RasterCache::GetIntegralTransCTM( - layer_offset_matrix)}}, -#endif - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}); + auto expected_draw_calls = + std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, + MockCanvas::DrawCall{ + 1, MockCanvas::ConcatMatrixData{layer_offset_matrix}}, + MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}); EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls); } diff --git a/flow/raster_cache.h b/flow/raster_cache.h index b51382a5c8d2d..2cbe07db5c6ba 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -62,13 +62,6 @@ class RasterCache { return bounds; } - static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) { - SkMatrix result = ctm; - result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX()); - result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY()); - return result; - } - // Return true if the cache is generated. // // We may return false and not generate the cache if diff --git a/flow/raster_cache_key.h b/flow/raster_cache_key.h index 5eae4d3dccacb..f5fd1e0ad1edb 100644 --- a/flow/raster_cache_key.h +++ b/flow/raster_cache_key.h @@ -15,11 +15,8 @@ template class RasterCacheKey { public: RasterCacheKey(ID id, const SkMatrix& ctm) : id_(id), matrix_(ctm) { - matrix_[SkMatrix::kMTransX] = SkScalarFraction(ctm.getTranslateX()); - matrix_[SkMatrix::kMTransY] = SkScalarFraction(ctm.getTranslateY()); -#ifndef SUPPORT_FRACTIONAL_TRANSLATION - FML_DCHECK(matrix_.getTranslateX() == 0 && matrix_.getTranslateY() == 0); -#endif + matrix_[SkMatrix::kMTransX] = 0; + matrix_[SkMatrix::kMTransY] = 0; } ID id() const { return id_; }