diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 2cd5bd4eb0465..5eeabcc3e89ad 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -49,6 +49,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 + uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c with: sarif_file: results.sarif diff --git a/.github/workflows/third_party_scan.yml b/.github/workflows/third_party_scan.yml index b87cfebc0763c..81d7c584fd00e 100644 --- a/.github/workflows/third_party_scan.yml +++ b/.github/workflows/third_party_scan.yml @@ -41,7 +41,7 @@ jobs: name: Vulnerability scanning needs: extract-deps - uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v1.7.4" + uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v1.8.1" with: # Download the artifact uploaded in extract-deps step download-artifact: osv-lockfile-${{github.sha}} diff --git a/DEPS b/DEPS index 21a61f85249c2..60536b4c023dc 100644 --- a/DEPS +++ b/DEPS @@ -14,7 +14,7 @@ vars = { 'flutter_git': 'https://flutter.googlesource.com', 'skia_git': 'https://skia.googlesource.com', 'llvm_git': 'https://llvm.googlesource.com', - 'skia_revision': '8375bdc6e191da6e39be965969cab4014bfbc8d1', + 'skia_revision': '86ee8cc615081303f575983bc2eb10e67b17a6ed', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. @@ -56,15 +56,15 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'c23e5814379374504ddad4f68c4ded939fcee0a2', + 'dart_revision': 'ffc8bb004a64f6357e3d5d1185e974e966f00931', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py 'dart_binaryen_rev': '654ee6e2504f11fb0e982a2cf276bafa750f694b', 'dart_boringssl_gen_rev': '9c7294fd58261a79794f5afaa26598cf1442ad20', 'dart_boringssl_rev': 'd24a38200fef19150eef00cad35b138936c08767', - 'dart_browser_launcher_rev': '7348ceae6508e5350771979c2951a54313303416', - 'dart_clock_rev': '7cbf08e36a92f14f22132d255846610c1b065324', + 'dart_browser_launcher_rev': '60126904a26b761d29b4f2d76292ff3c089160de', + 'dart_clock_rev': 'ad428ea8b75fa0d7ba629791552d40478745c54a', 'dart_collection_rev': '9354f386de3c57f5486b01ab4dfa1a2f033307d9', 'dart_devtools_rev': '70375f6c6d81faa8f3069aa6dcf2a98c69445455', 'dart_libprotobuf_rev': '24487dd1045c7f3d64a21f38a3f0c06cc4cf2edb', @@ -72,12 +72,12 @@ vars = { 'dart_protobuf_gn_rev': 'ca669f79945418f6229e4fef89b666b2a88cbb10', 'dart_protobuf_rev': 'ccf104dbc36929c0f8708285d5f3a8fae206343e', 'dart_pub_rev': 'ea4a1c854690d3abceb92c8cc2c6454470f9d5a7', - 'dart_tools_rev': '4c606868746da309963589e99b39d2017c582975', - 'dart_watcher_rev': 'f312f1f81c5272ad34ed5c40f29ba8599caed3ef', - 'dart_web_rev': '2ae509e7e733c3e752b9524aded3cfffc6f64a2f', + 'dart_tools_rev': '43a8582a85d2220b5f1ca8383d97587792085b36', + 'dart_watcher_rev': '0484625589d8512b36a7ad898a6cc6351d24c556', + 'dart_web_rev': 'e4c4d8126466e28dc137890b8f999da59bdedddd', 'dart_webdev_rev': '75417c09181c97786d9539a662834bed9d2f1e77', - 'dart_webkit_inspection_protocol_rev': '5740cc91eaeb13a02007b77b128fccf4b056db6e', - 'dart_yaml_edit_rev': 'ad3292cd8e893747fae73a7c552d8c858a2be986', + 'dart_webkit_inspection_protocol_rev': '32fffa53df3f54005c742ddf4f859fb585a6b254', + 'dart_yaml_edit_rev': '57a28daea82a3f00f57a90d5ea6df6a458b2f781', 'ocmock_rev': 'c4ec0e3a7a9f56cfdbd0aa01f4f97bb4b75c5ef8', # v3.7.1 @@ -255,7 +255,7 @@ vars = { # The version / instance id of the cipd:chromium/fuchsia/gn-sdk which will be # used altogether with fuchsia-sdk to generate gn based build rules. - 'fuchsia_gn_sdk_version': 'RgErspyYHapUO2SpcW-vo2p8yaRUMUrq0eWjRVPfQjoC', + 'fuchsia_gn_sdk_version': 'sbh76PYVTMxav4ACTgA-TXWcbZTZcWWjsqATCxrGIvwC', } gclient_gn_args_file = 'src/flutter/third_party/dart/build/config/gclient_args.gni' @@ -277,7 +277,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + '6c01dbca494b78e32f9e4aa704514faabfba74e8', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '8c2d66fa4e6298894425f5bdd0591bc5b1154c53', 'src/flutter/third_party/depot_tools': Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '580b4ff3f5cd0dcaa2eacda28cefe0f45320e8f7', @@ -307,7 +307,7 @@ deps = { Var('chromium_git') + '/external/github.com/google/flatbuffers' + '@' + '0a80646371179f8a7a5c1f42c31ee1d44dcf6709', 'src/flutter/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '98f2494518c2dbb9c488e83e507b070ea5910e95', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '43953f57b037778a1b8005564afabe214834f7bd', 'src/flutter/third_party/gtest-parallel': Var('chromium_git') + '/external/github.com/google/gtest-parallel' + '@' + '38191e2733d7cbaeaef6a3f1a942ddeb38a2ad14', @@ -353,19 +353,19 @@ deps = { Var('dart_git') + '/args.git@6a5a2e6b1f0020b873c7ffbdd36a784c4f9ee300', 'src/flutter/third_party/dart/third_party/pkg/async': - Var('dart_git') + '/async.git@d7c0cd5a458308ab5e5a0d0deebdce32c4391ec6', + Var('dart_git') + '/async.git@c0d81f8699682d01d657a9bf827107d11904a247', 'src/flutter/third_party/dart/third_party/pkg/bazel_worker': Var('dart_git') + '/bazel_worker.git@c76d7c86381a6ed594641ba03b55c65b84ee11a6', 'src/flutter/third_party/dart/third_party/pkg/boolean_selector': - Var('dart_git') + '/boolean_selector.git@62f82f6a333b419b457e62cadc17b7a9c0545873', + Var('dart_git') + '/boolean_selector.git@c5468f44fd9ca0ea3435e1a0a84ff9b6fac38261', 'src/flutter/third_party/dart/third_party/pkg/browser_launcher': Var('dart_git') + '/browser_launcher.git' + '@' + Var('dart_browser_launcher_rev'), 'src/flutter/third_party/dart/third_party/pkg/cli_util': - Var('dart_git') + '/cli_util.git@c37d5e14f50e72a268c1ad86149cecfa4b58c494', + Var('dart_git') + '/cli_util.git@64192706344d0598784bebe1abc4a9bfc2608de0', 'src/flutter/third_party/dart/third_party/pkg/clock': Var('dart_git') + '/clock.git' + '@' + Var('dart_clock_rev'), @@ -374,13 +374,13 @@ deps = { Var('dart_git') + '/collection.git' + '@' + Var('dart_collection_rev'), 'src/flutter/third_party/dart/third_party/pkg/convert': - Var('dart_git') + '/convert.git@0c9eab7d4656be97329c4970659afd53a78910e6', + Var('dart_git') + '/convert.git@9035cafefc1da4315f26058734d0c2a19d5ab56a', 'src/flutter/third_party/dart/third_party/pkg/crypto': - Var('dart_git') + '/crypto.git@813e35e913d12e16de67ac57523cd0ff4b07c012', + Var('dart_git') + '/crypto.git@1216790ba704a0ab194f9cd0da2d65e1767f3342', 'src/flutter/third_party/dart/third_party/pkg/csslib': - Var('dart_git') + '/csslib.git@b70fef222c8a98abca39c3f729ec34632089697e', + Var('dart_git') + '/csslib.git@192d720f121792ab05ca157ea280edc7e0410e9c', 'src/flutter/third_party/dart/third_party/pkg/dart_style': Var('dart_git') + '/dart_style.git@a6ad7693555a9add6f98ad6fd94de80d35c89415', @@ -392,16 +392,16 @@ deps = { Var('dart_git') + '/external/github.com/google/file.dart@07cacaed6679a173e29176747e6ce0325742749f', 'src/flutter/third_party/dart/third_party/pkg/fixnum': - Var('dart_git') + '/fixnum.git@a8157d87f17d5184e210403f2ed63d354b854132', + Var('dart_git') + '/fixnum.git@6c19e60366ce3d5edfaed51a7c12c98e7977977e', 'src/flutter/third_party/dart/third_party/pkg/glob': Var('dart_git') + '/glob.git@6d3ba5ec02817e62d17ace040590bb81a3e1242f', 'src/flutter/third_party/dart/third_party/pkg/html': - Var('dart_git') + '/html.git@f6c2c71dd6dc23bda3b4c5ac1290cf7207748071', + Var('dart_git') + '/html.git@0da420ca1e196cda54ede476d0d8d3ecf55375ef', 'src/flutter/third_party/dart/third_party/pkg/http': - Var('dart_git') + '/http.git@bf96551406600a2ec520a4248ff635bfd268edeb', + Var('dart_git') + '/http.git@8d893851904d8cd292a66e39812b59aca2cc4d96', 'src/flutter/third_party/dart/third_party/pkg/http_multi_server': Var('dart_git') + '/http_multi_server.git@25941e260658efb324de857e6022f418faf9bdd1', @@ -419,19 +419,19 @@ deps = { Var('dart_git') + '/leak_tracker.git@f5620600a5ce1c44f65ddaa02001e200b096e14c', 'src/flutter/third_party/dart/third_party/pkg/logging': - Var('dart_git') + '/logging.git@240ec33e23720091e0e5a029d569a3770ddccf1c', + Var('dart_git') + '/logging.git@6c3fb37fecb2e30415072f327b834a3e95517fa9', 'src/flutter/third_party/dart/third_party/pkg/markdown': - Var('dart_git') + '/markdown.git@3d8d7a8f14b74bb646bb6e4ae35e0bf2beb74154', + Var('dart_git') + '/markdown.git@62424376d0b5fe35a2957b3caed4b75db010ba82', 'src/flutter/third_party/dart/third_party/pkg/matcher': - Var('dart_git') + '/matcher.git@0abd4054c47a923486a6c0c04b5c974ba13ad2da', + Var('dart_git') + '/matcher.git@d6d573d0f8d65b36550ce62aad3ce6b5e987b642', 'src/flutter/third_party/dart/third_party/pkg/mime': - Var('dart_git') + '/mime.git@fd7010b00ca028918cbd90abc347f98b88b2d00f', + Var('dart_git') + '/mime.git@11fec7d6df509a4efd554051cc27e3bf82df9c96', 'src/flutter/third_party/dart/third_party/pkg/mockito': - Var('dart_git') + '/mockito.git@9deddcfa4b6b6c1ecb3111891c20cc46c115569d', + Var('dart_git') + '/mockito.git@a7fdf7101fbd31132a59188a6057d21004345927', 'src/flutter/third_party/dart/third_party/pkg/native': Var('dart_git') + '/native.git@fcc783c1d2777555616dfc850f131878ea5d88a9', @@ -440,10 +440,10 @@ deps = { Var('dart_git') + '/package_config.git@903a0e528f91aef90821c8f5eaafbc1ae27198ab', 'src/flutter/third_party/dart/third_party/pkg/path': - Var('dart_git') + '/path.git@04807b61c25f98f328b322ec511451f9f86f98bb', + Var('dart_git') + '/path.git@e969f42ed112dd702a9453beb9df6c12ae2d3805', 'src/flutter/third_party/dart/third_party/pkg/pool': - Var('dart_git') + '/pool.git@832c5ab5eaee444354a8c796f7998bf744f169af', + Var('dart_git') + '/pool.git@924fb04353cec915d927f9f1aed88e2eda92b98a', 'src/flutter/third_party/dart/third_party/pkg/protobuf': Var('dart_git') + '/protobuf.git' + '@' + Var('dart_protobuf_rev'), @@ -452,13 +452,13 @@ deps = { Var('dart_git') + '/pub.git' + '@' + Var('dart_pub_rev'), 'src/flutter/third_party/dart/third_party/pkg/pub_semver': - Var('dart_git') + '/pub_semver.git@dfcad38866fb1e94e8ca91bff3dddd5189fb0794', + Var('dart_git') + '/pub_semver.git@d9e5ee68a350fbf4319bd4dfcb895fc016337d3a', 'src/flutter/third_party/dart/third_party/pkg/shelf': - Var('dart_git') + '/shelf.git@2536c15a562cb183dabbc628824a215663830325', + Var('dart_git') + '/shelf.git@9f2dffecbe8f219146a077e401758602752d486a', 'src/flutter/third_party/dart/third_party/pkg/source_map_stack_trace': - Var('dart_git') + '/source_map_stack_trace.git@96a8213dacf7cd42aefb1311491a4169826f98d2', + Var('dart_git') + '/source_map_stack_trace.git@741b6ceb4b6cdb8ff620664337d7ecc63ca52cc1', 'src/flutter/third_party/dart/third_party/pkg/source_maps': Var('dart_git') + '/source_maps.git@caa79c2011015759c6cf3299f299f5cccdf8bb61', @@ -467,34 +467,34 @@ deps = { Var('dart_git') + '/source_span.git@89520f3009e332ce2b6675f71dca166521c36cc4', 'src/flutter/third_party/dart/third_party/pkg/sse': - Var('dart_git') + '/sse.git@7dcde164d5bfe707441f206379ef33e7509e2aac', + Var('dart_git') + '/sse.git@52d042ff9ab2d0e5bc26805d74a03077a67861e1', 'src/flutter/third_party/dart/third_party/pkg/stack_trace': - Var('dart_git') + '/stack_trace.git@ab09060b82c936c38c04eb49c1154b83f6648349', + Var('dart_git') + '/stack_trace.git@4fd3e2a2dc6611febf4cfb9197ebf9e60fc6a34d', 'src/flutter/third_party/dart/third_party/pkg/stream_channel': - Var('dart_git') + '/stream_channel.git@dc620d233e0bea618ee22227d4fd487f055b4ead', + Var('dart_git') + '/stream_channel.git@28a65331aa2d66a5e953205aa462bcdb1e240a5b', 'src/flutter/third_party/dart/third_party/pkg/string_scanner': - Var('dart_git') + '/string_scanner.git@e1cab8f0538b50f6d7180598752cf5a7e07e74db', + Var('dart_git') + '/string_scanner.git@0de03b5279a04aa05052ce306f90fca473c6fd1a', 'src/flutter/third_party/dart/third_party/pkg/tar': Var('dart_git') + '/external/github.com/simolus3/tar.git@552a49d7595e444184d4f91e9afd533aa253a31d', 'src/flutter/third_party/dart/third_party/pkg/term_glyph': - Var('dart_git') + '/term_glyph.git@6c2a9770e786f83bb1a863c6947dde5dcbebdbd2', + Var('dart_git') + '/term_glyph.git@38a158f55006cf30942c928171ea601ee5e0308f', 'src/flutter/third_party/dart/third_party/pkg/test': - Var('dart_git') + '/test.git@329c6dff4dfcb178ba6c7009cf1c1b9215b317aa', + Var('dart_git') + '/test.git@3256c23cc753a184bb3bf27610a7c8410735e3ac', 'src/flutter/third_party/dart/third_party/pkg/test_reflective_loader': - Var('dart_git') + '/test_reflective_loader.git@816942eaeeac30cc59d8699f1e94ad779cc53c06', + Var('dart_git') + '/test_reflective_loader.git@6e648863b39aab8d0204e769d25805eea9db0ac4', 'src/flutter/third_party/dart/third_party/pkg/tools': Var('dart_git') + '/tools.git' + '@' + Var('dart_tools_rev'), 'src/flutter/third_party/dart/third_party/pkg/typed_data': - Var('dart_git') + '/typed_data.git@85299290551297a28202b6e7a177bb787f790ffd', + Var('dart_git') + '/typed_data.git@365468a74251c930a463daf5b8f13227e269111a', 'src/flutter/third_party/dart/third_party/pkg/watcher': Var('dart_git') + '/watcher.git' + '@' + Var('dart_watcher_rev'), @@ -503,7 +503,7 @@ deps = { Var('dart_git') + '/web.git' + '@' + Var('dart_web_rev'), 'src/flutter/third_party/dart/third_party/pkg/web_socket_channel': - Var('dart_git') + '/web_socket_channel.git@bf69990738f173c07e67cf6945551194bc8c2d92', + Var('dart_git') + '/web_socket_channel.git@8e95ea75302180af075295f7dd7ffe922e26f789', 'src/flutter/third_party/dart/third_party/pkg/webdev': Var('dart_git') + '/webdev.git' + '@' + Var('dart_webdev_rev'), @@ -512,7 +512,7 @@ deps = { Var('dart_git') + '/external/github.com/google/webkit_inspection_protocol.dart.git' + '@' + Var('dart_webkit_inspection_protocol_rev'), 'src/flutter/third_party/dart/third_party/pkg/yaml': - Var('dart_git') + '/yaml.git@4cf24ca3bbcb2cd8cbea32fdd355ee5d0a597247', + Var('dart_git') + '/yaml.git@30fd9e0cd49b2e04f74769f9b24a0300e400403e', 'src/flutter/third_party/dart/third_party/pkg/yaml_edit': Var('dart_git') + '/yaml_edit.git' + '@' + Var('dart_yaml_edit_rev'), @@ -969,7 +969,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'LkXpxHsQlkPT4mmJ7i9vS0-GQmceOV-FpTF-9wxfMFUC' + 'version': '-VgqOfoW5sf04SuJh64NbuVnDIwiyl7NyTAD4fsTLNkC' } ], 'condition': 'download_fuchsia_deps and not download_fuchsia_sdk', diff --git a/ci/licenses_golden/licenses_dart b/ci/licenses_golden/licenses_dart index 1a758effa7c98..70d912e6706e0 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: 6356c8f33f6d603844c3b2ed56745d26 +Signature: 987cab3f3e3a6e4e7248b7606f819b61 ==================================================================================================== LIBRARY: dart @@ -4751,7 +4751,7 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. -You may obtain a copy of this library's Source Code Form from: https://dart.googlesource.com/sdk/+/c23e5814379374504ddad4f68c4ded939fcee0a2 +You may obtain a copy of this library's Source Code Form from: https://dart.googlesource.com/sdk/+/ffc8bb004a64f6357e3d5d1185e974e966f00931 /third_party/fallback_root_certificates/ ==================================================================================================== diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index 370f75a0225af..35004983987c1 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: d94be6f5460ab5223d58b2c2defd09d8 +Signature: a0d92f936626b8cb89b8871e340b3f7f ==================================================================================================== LIBRARY: fuchsia_sdk diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 3087654137624..bf6c0791970fc 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 2856c45f73ed1da0f00d150abb3fcc36 +Signature: ae53123dde9d20d55e68125cbde51435 ==================================================================================================== LIBRARY: etc1 diff --git a/display_list/display_list.h b/display_list/display_list.h index bb67c435cc6d7..35c19ef9d4a0b 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -98,11 +98,9 @@ namespace flutter { V(TransformReset) \ \ V(ClipIntersectRect) \ - V(ClipIntersectOval) \ V(ClipIntersectRRect) \ V(ClipIntersectPath) \ V(ClipDifferenceRect) \ - V(ClipDifferenceOval) \ V(ClipDifferenceRRect) \ V(ClipDifferencePath) \ \ diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index a3d362eefad3e..635d38af7c8a9 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -3439,9 +3439,11 @@ TEST_F(DisplayListTest, ImpellerPathPreferenceIsHonored) { }; DisplayListBuilder builder; - builder.DrawPath(kTestPath1, DlPaint()); - builder.ClipPath(kTestPath1, ClipOp::kIntersect, true); - builder.DrawShadow(kTestPath1, DlColor::kBlue(), 1.0f, true, 1.0f); + builder.DrawPath(SkPath::Rect(SkRect::MakeLTRB(0, 0, 100, 100)), DlPaint()); + builder.ClipPath(SkPath::Rect(SkRect::MakeLTRB(0, 0, 100, 100)), + ClipOp::kIntersect, true); + builder.DrawShadow(SkPath::Rect(SkRect::MakeLTRB(20, 20, 80, 80)), + DlColor::kBlue(), 1.0f, true, 1.0f); auto display_list = builder.Build(); { @@ -4330,66 +4332,36 @@ TEST_F(DisplayListTest, DrawDisplayListForwardsBackdropFlag) { #define CLIP_EXPECTOR(name) ClipExpector name(__FILE__, __LINE__) -struct ClipExpectation { - std::variant shape; - bool is_oval; - ClipOp clip_op; - bool is_aa; - - std::string shape_name() { - switch (shape.index()) { - case 0: - return is_oval ? "SkOval" : "SkRect"; - case 1: - return "SkRRect"; - case 2: - return "SkPath"; - default: - return "Unknown"; - } - } -}; - -::std::ostream& operator<<(::std::ostream& os, const ClipExpectation& expect) { - os << "Expectation("; - switch (expect.shape.index()) { - case 0: - os << std::get(expect.shape); - if (expect.is_oval) { - os << " (oval)"; - } - break; - case 1: - os << std::get(expect.shape); - break; - case 2: - os << std::get(expect.shape); - break; - case 3: - os << "Unknown"; - } - os << ", " << expect.clip_op; - os << ", " << expect.is_aa; - os << ")"; - return os; -} - class ClipExpector : public virtual DlOpReceiver, virtual IgnoreAttributeDispatchHelper, virtual IgnoreTransformDispatchHelper, virtual IgnoreDrawDispatchHelper { public: + struct Expectation { + std::variant shape; + ClipOp clip_op; + bool is_aa; + + std::string shape_name() { + switch (shape.index()) { + case 0: + return "SkRect"; + case 1: + return "SkRRect"; + case 2: + return "SkPath"; + default: + return "Unknown"; + } + } + }; + // file and line supplied automatically from CLIP_EXPECTOR macro explicit ClipExpector(const std::string& file, int line) : file_(file), line_(line) {} ~ClipExpector() { // EXPECT_EQ(index_, clip_expectations_.size()) << label(); - while (index_ < clip_expectations_.size()) { - auto expect = clip_expectations_[index_]; - FML_LOG(ERROR) << "leftover clip shape[" << index_ << "] = " << expect; - index_++; - } } ClipExpector& addExpectation(const SkRect& rect, @@ -4397,19 +4369,6 @@ class ClipExpector : public virtual DlOpReceiver, bool is_aa = false) { clip_expectations_.push_back({ .shape = rect, - .is_oval = false, - .clip_op = clip_op, - .is_aa = is_aa, - }); - return *this; - } - - ClipExpector& addOvalExpectation(const SkRect& rect, - ClipOp clip_op = ClipOp::kIntersect, - bool is_aa = false) { - clip_expectations_.push_back({ - .shape = rect, - .is_oval = true, .clip_op = clip_op, .is_aa = is_aa, }); @@ -4421,7 +4380,6 @@ class ClipExpector : public virtual DlOpReceiver, bool is_aa = false) { clip_expectations_.push_back({ .shape = rrect, - .is_oval = false, .clip_op = clip_op, .is_aa = is_aa, }); @@ -4433,7 +4391,6 @@ class ClipExpector : public virtual DlOpReceiver, bool is_aa = false) { clip_expectations_.push_back({ .shape = path, - .is_oval = false, .clip_op = clip_op, .is_aa = is_aa, }); @@ -4445,11 +4402,6 @@ class ClipExpector : public virtual DlOpReceiver, bool is_aa) override { check(rect, clip_op, is_aa); } - void clipOval(const SkRect& bounds, - DlCanvas::ClipOp clip_op, - bool is_aa) override { - check(bounds, clip_op, is_aa, true); - } void clipRRect(const SkRRect& rrect, DlCanvas::ClipOp clip_op, bool is_aa) override { @@ -4463,23 +4415,22 @@ class ClipExpector : public virtual DlOpReceiver, private: size_t index_ = 0; - std::vector clip_expectations_; + std::vector clip_expectations_; template - void check(T shape, ClipOp clip_op, bool is_aa, bool is_oval = false) { + void check(T shape, ClipOp clip_op, bool is_aa) { ASSERT_LT(index_, clip_expectations_.size()) << label() << std::endl - << "extra clip shape = " << shape << (is_oval ? " (oval)" : ""); + << "extra clip shape = " << shape; auto expected = clip_expectations_[index_]; + EXPECT_EQ(expected.clip_op, clip_op) << label(); + EXPECT_EQ(expected.is_aa, is_aa) << label(); if (!std::holds_alternative(expected.shape)) { EXPECT_TRUE(std::holds_alternative(expected.shape)) << label() << ", expected type: " << expected.shape_name(); } else { EXPECT_EQ(std::get(expected.shape), shape) << label(); } - EXPECT_EQ(expected.is_oval, is_oval) << label(); - EXPECT_EQ(expected.clip_op, clip_op) << label(); - EXPECT_EQ(expected.is_aa, is_aa) << label(); index_++; } @@ -4619,47 +4570,9 @@ TEST_F(DisplayListTest, ClipRectNestedNonCullingComplex) { cull_dl->Dispatch(expector); } -TEST_F(DisplayListTest, ClipOvalCulling) { - auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - // A 10x10 rectangle extends 5x5 from the center to each corner. To have - // an oval that encompasses that rectangle, the radius must be at least - // length(5, 5), or 7.071+ so we expand the radius 5 square clip by 2.072 - // on each side to barely contain the corners of the square. - auto encompassing_oval = clip.makeOutset(2.072f, 2.072f); - - DisplayListBuilder cull_builder; - cull_builder.ClipRect(clip, ClipOp::kIntersect, false); - cull_builder.ClipOval(encompassing_oval, ClipOp::kIntersect, false); - auto cull_dl = cull_builder.Build(); - - CLIP_EXPECTOR(expector); - expector.addExpectation(clip, ClipOp::kIntersect, false); - cull_dl->Dispatch(expector); -} - -TEST_F(DisplayListTest, ClipOvalNonCulling) { - auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - // A 10x10 rectangle extends 5x5 from the center to each corner. To have - // an oval that encompasses that rectangle, the radius must be at least - // length(5, 5), or 7.071+ so we expand the radius 5 square clip by 2.072 - // on each side to barely exclude the corners of the square. - auto non_encompassing_oval = clip.makeOutset(2.071f, 2.071f); - - DisplayListBuilder cull_builder; - cull_builder.ClipRect(clip, ClipOp::kIntersect, false); - cull_builder.ClipOval(non_encompassing_oval, ClipOp::kIntersect, false); - auto cull_dl = cull_builder.Build(); - - CLIP_EXPECTOR(expector); - expector.addExpectation(clip, ClipOp::kIntersect, false); - expector.addOvalExpectation(non_encompassing_oval, ClipOp::kIntersect, false); - cull_dl->Dispatch(expector); -} - TEST_F(DisplayListTest, ClipRRectCulling) { auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); auto rrect = SkRRect::MakeRectXY(clip.makeOutset(2.0f, 2.0f), 2.0f, 2.0f); - ASSERT_FALSE(rrect.isOval()); DisplayListBuilder cull_builder; cull_builder.ClipRect(clip, ClipOp::kIntersect, false); @@ -4673,8 +4586,7 @@ TEST_F(DisplayListTest, ClipRRectCulling) { TEST_F(DisplayListTest, ClipRRectNonCulling) { auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - auto rrect = SkRRect::MakeRectXY(clip.makeOutset(1.0f, 1.0f), 4.0f, 4.0f); - ASSERT_FALSE(rrect.isOval()); + auto rrect = SkRRect::MakeRectXY(clip.makeOutset(2.0f, 2.0f), 12.0f, 12.0f); DisplayListBuilder cull_builder; cull_builder.ClipRect(clip, ClipOp::kIntersect, false); @@ -4749,52 +4661,9 @@ TEST_F(DisplayListTest, ClipPathRectNonCulling) { cull_dl->Dispatch(expector); } -TEST_F(DisplayListTest, ClipPathOvalCulling) { - auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - // A 10x10 rectangle extends 5x5 from the center to each corner. To have - // an oval that encompasses that rectangle, the radius must be at least - // length(5, 5), or 7.071+ so we expand the radius 5 square clip by 2.072 - // on each side to barely contain the corners of the square. - auto encompassing_oval = clip.makeOutset(2.072f, 2.072f); - SkPath path; - path.addOval(encompassing_oval); - - DisplayListBuilder cull_builder; - cull_builder.ClipRect(clip, ClipOp::kIntersect, false); - cull_builder.ClipPath(path, ClipOp::kIntersect, false); - auto cull_dl = cull_builder.Build(); - - CLIP_EXPECTOR(expector); - expector.addExpectation(clip, ClipOp::kIntersect, false); - cull_dl->Dispatch(expector); -} - -TEST_F(DisplayListTest, ClipPathOvalNonCulling) { - auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - // A 10x10 rectangle extends 5x5 from the center to each corner. To have - // an oval that encompasses that rectangle, the radius must be at least - // length(5, 5), or 7.071+ so we expand the radius 5 square clip by 2.072 - // on each side to barely exclude the corners of the square. - auto non_encompassing_oval = clip.makeOutset(2.071f, 2.071f); - SkPath path; - path.addOval(non_encompassing_oval); - - DisplayListBuilder cull_builder; - cull_builder.ClipRect(clip, ClipOp::kIntersect, false); - cull_builder.ClipPath(path, ClipOp::kIntersect, false); - auto cull_dl = cull_builder.Build(); - - CLIP_EXPECTOR(expector); - expector.addExpectation(clip, ClipOp::kIntersect, false); - // Builder will not cull this clip, but it will turn it into a ClipOval - expector.addOvalExpectation(non_encompassing_oval, ClipOp::kIntersect, false); - cull_dl->Dispatch(expector); -} - TEST_F(DisplayListTest, ClipPathRRectCulling) { auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); auto rrect = SkRRect::MakeRectXY(clip.makeOutset(2.0f, 2.0f), 2.0f, 2.0f); - ASSERT_FALSE(rrect.isOval()); SkPath path; path.addRRect(rrect); @@ -4810,8 +4679,7 @@ TEST_F(DisplayListTest, ClipPathRRectCulling) { TEST_F(DisplayListTest, ClipPathRRectNonCulling) { auto clip = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - auto rrect = SkRRect::MakeRectXY(clip.makeOutset(1.0f, 1.0f), 4.0f, 4.0f); - ASSERT_FALSE(rrect.isOval()); + auto rrect = SkRRect::MakeRectXY(clip.makeOutset(2.0f, 2.0f), 12.0f, 12.0f); SkPath path; path.addRRect(rrect); @@ -4856,323 +4724,5 @@ TEST_F(DisplayListTest, RecordLargeVertices) { } } -TEST_F(DisplayListTest, DrawRectRRectPromoteToDrawRect) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - - DisplayListBuilder builder; - builder.DrawRRect(SkRRect::MakeRect(rect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawRect(rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, DrawOvalRRectPromoteToDrawOval) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - - DisplayListBuilder builder; - builder.DrawRRect(SkRRect::MakeOval(rect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawOval(rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, DrawRectPathPromoteToDrawRect) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - - DisplayListBuilder builder; - builder.DrawPath(SkPath::Rect(rect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawRect(rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, DrawOvalPathPromoteToDrawOval) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - - DisplayListBuilder builder; - builder.DrawPath(SkPath::Oval(rect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawOval(rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, DrawRRectPathPromoteToDrawRRect) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect rrect = SkRRect::MakeRectXY(rect, 2.0f, 2.0f); - - DisplayListBuilder builder; - builder.DrawPath(SkPath::RRect(rrect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawRRect(rrect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, DrawRectRRectPathPromoteToDrawRect) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect rrect = SkRRect::MakeRect(rect); - - DisplayListBuilder builder; - builder.DrawPath(SkPath::RRect(rrect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawRect(rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, DrawOvalRRectPathPromoteToDrawOval) { - SkRect rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect rrect = SkRRect::MakeOval(rect); - - DisplayListBuilder builder; - builder.DrawPath(SkPath::RRect(rrect), DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.DrawOval(rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipRectRRectPromoteToClipRect) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - - DisplayListBuilder builder; - builder.ClipRRect(SkRRect::MakeRect(clip_rect), ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipRect(clip_rect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipOvalRRectPromoteToClipOval) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - - DisplayListBuilder builder; - builder.ClipRRect(SkRRect::MakeOval(clip_rect), ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipOval(clip_rect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipRectPathPromoteToClipRect) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::Rect(clip_rect); - ASSERT_TRUE(clip_path.isRect(nullptr)); - ASSERT_FALSE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipRect(clip_rect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipOvalPathPromoteToClipOval) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::Oval(clip_rect); - ASSERT_TRUE(clip_path.isOval(nullptr)); - ASSERT_FALSE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipOval(clip_rect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipRRectPathPromoteToClipRRect) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2.0f, 2.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::RRect(clip_rrect); - ASSERT_TRUE(clip_path.isRRect(nullptr)); - ASSERT_FALSE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipRRect(clip_rrect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipRectInversePathNoPromoteToClipRect) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::Rect(clip_rect); - clip_path.toggleInverseFillType(); - ASSERT_TRUE(clip_path.isRect(nullptr)); - ASSERT_TRUE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - // Non-promoting tests can't use DL comparisons to verify that the - // promotion isn't happening because the test and expectation builders - // would both apply or not apply the same optimization. For this case - // we use the CLIP_EXPECTOR instead to see exactly which type of - // clip operation was recorded. - CLIP_EXPECTOR(expector); - expector.addExpectation(clip_path, ClipOp::kIntersect, false); - dl->Dispatch(expector); -} - -TEST_F(DisplayListTest, ClipOvalInversePathNoPromoteToClipOval) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::Oval(clip_rect); - clip_path.toggleInverseFillType(); - ASSERT_TRUE(clip_path.isOval(nullptr)); - ASSERT_TRUE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - // Non-promoting tests can't use DL comparisons to verify that the - // promotion isn't happening because the test and expectation builders - // would both apply or not apply the same optimization. For this case - // we use the CLIP_EXPECTOR instead to see exactly which type of - // clip operation was recorded. - CLIP_EXPECTOR(expector); - expector.addExpectation(clip_path, ClipOp::kIntersect, false); - dl->Dispatch(expector); -} - -TEST_F(DisplayListTest, ClipRRectInversePathNoPromoteToClipRRect) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2.0f, 2.0f); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::RRect(clip_rrect); - clip_path.toggleInverseFillType(); - ASSERT_TRUE(clip_path.isRRect(nullptr)); - ASSERT_TRUE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - // Non-promoting tests can't use DL comparisons to verify that the - // promotion isn't happening because the test and expectation builders - // would both apply or not apply the same optimization. For this case - // we use the CLIP_EXPECTOR instead to see exactly which type of - // clip operation was recorded. - CLIP_EXPECTOR(expector); - expector.addExpectation(clip_path, ClipOp::kIntersect, false); - dl->Dispatch(expector); -} - -TEST_F(DisplayListTest, ClipRectRRectPathPromoteToClipRect) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect clip_rrect = SkRRect::MakeRect(clip_rect); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::RRect(clip_rrect); - ASSERT_TRUE(clip_path.isRRect(nullptr)); - ASSERT_FALSE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipRect(clip_rect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - -TEST_F(DisplayListTest, ClipOvalRRectPathPromoteToClipOval) { - SkRect clip_rect = SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f); - SkRRect clip_rrect = SkRRect::MakeOval(clip_rect); - SkRect draw_rect = clip_rect.makeOutset(2.0f, 2.0f); - SkPath clip_path = SkPath::RRect(clip_rrect); - ASSERT_TRUE(clip_path.isRRect(nullptr)); - ASSERT_FALSE(clip_path.isInverseFillType()); - - DisplayListBuilder builder; - builder.ClipPath(clip_path, ClipOp::kIntersect, false); - // Include a rendering op in case DlBuilder ever removes unneeded clips - builder.DrawRect(draw_rect, DlPaint()); - auto dl = builder.Build(); - - DisplayListBuilder expected; - expected.ClipOval(clip_rect, ClipOp::kIntersect, false); - expected.DrawRect(draw_rect, DlPaint()); - auto expect_dl = expected.Build(); - - DisplayListsEQ_Verbose(dl, expect_dl); -} - } // namespace testing } // namespace flutter diff --git a/display_list/dl_builder.cc b/display_list/dl_builder.cc index 387455327e85f..98772c0d7a3ab 100644 --- a/display_list/dl_builder.cc +++ b/display_list/dl_builder.cc @@ -963,50 +963,14 @@ void DisplayListBuilder::ClipRect(const SkRect& rect, break; } } -void DisplayListBuilder::ClipOval(const SkRect& bounds, - ClipOp clip_op, - bool is_aa) { - if (!bounds.isFinite()) { - return; - } - if (current_info().is_nop) { - return; - } - if (current_info().has_valid_clip && - clip_op == DlCanvas::ClipOp::kIntersect && - layer_local_state().oval_covers_cull(bounds)) { - return; - } - global_state().clipOval(bounds, clip_op, is_aa); - layer_local_state().clipOval(bounds, clip_op, is_aa); - if (global_state().is_cull_rect_empty() || - layer_local_state().is_cull_rect_empty()) { - current_info().is_nop = true; - return; - } - current_info().has_valid_clip = true; - checkForDeferredSave(); - switch (clip_op) { - case ClipOp::kIntersect: - Push(0, bounds, is_aa); - break; - case ClipOp::kDifference: - Push(0, bounds, is_aa); - break; - } -} void DisplayListBuilder::ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) { - if (current_info().is_nop) { - return; - } if (rrect.isRect()) { clipRect(rrect.rect(), clip_op, is_aa); return; } - if (rrect.isOval()) { - clipOval(rrect.rect(), clip_op, is_aa); + if (current_info().is_nop) { return; } if (current_info().has_valid_clip && @@ -1044,11 +1008,12 @@ void DisplayListBuilder::ClipPath(const SkPath& path, this->clipRect(rect, clip_op, is_aa); return; } + SkRRect rrect; if (path.isOval(&rect)) { - this->clipOval(rect, clip_op, is_aa); + rrect.setOval(rect); + this->clipRRect(rrect, clip_op, is_aa); return; } - SkRRect rrect; if (path.isRRect(&rrect)) { this->clipRRect(rrect, clip_op, is_aa); return; @@ -1223,22 +1188,6 @@ void DisplayListBuilder::DrawDRRect(const SkRRect& outer, drawDRRect(outer, inner); } void DisplayListBuilder::drawPath(const SkPath& path) { - if (!path.isInverseFillType()) { - SkRect rect; - if (path.isRect(&rect)) { - drawRect(rect); - return; - } - if (path.isOval(&rect)) { - drawOval(rect); - return; - } - SkRRect rrect; - if (path.isRRect(&rrect)) { - drawRRect(rrect); - return; - } - } DisplayListAttributeFlags flags = kDrawPathFlags; OpResult result = PaintResult(current_, flags); if (result != OpResult::kNoEffect) { diff --git a/display_list/dl_builder.h b/display_list/dl_builder.h index dc75e2d37f6af..b1a458f68eec9 100644 --- a/display_list/dl_builder.h +++ b/display_list/dl_builder.h @@ -117,10 +117,6 @@ class DisplayListBuilder final : public virtual DlCanvas, ClipOp clip_op = ClipOp::kIntersect, bool is_aa = false) override; // |DlCanvas| - void ClipOval(const SkRect& bounds, - ClipOp clip_op = ClipOp::kIntersect, - bool is_aa = false) override; - // |DlCanvas| void ClipRRect(const SkRRect& rrect, ClipOp clip_op = ClipOp::kIntersect, bool is_aa = false) override; @@ -404,10 +400,6 @@ class DisplayListBuilder final : public virtual DlCanvas, ClipRect(rect, clip_op, is_aa); } // |DlOpReceiver| - void clipOval(const SkRect& bounds, ClipOp clip_op, bool is_aa) override { - ClipOval(bounds, clip_op, is_aa); - } - // |DlOpReceiver| void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override { ClipRRect(rrect, clip_op, is_aa); } diff --git a/display_list/dl_canvas.h b/display_list/dl_canvas.h index 8fa4ad923f307..ab505777aeae2 100644 --- a/display_list/dl_canvas.h +++ b/display_list/dl_canvas.h @@ -105,9 +105,6 @@ class DlCanvas { virtual void ClipRect(const SkRect& rect, ClipOp clip_op = ClipOp::kIntersect, bool is_aa = false) = 0; - virtual void ClipOval(const SkRect& bounds, - ClipOp clip_op = ClipOp::kIntersect, - bool is_aa = false) = 0; virtual void ClipRRect(const SkRRect& rrect, ClipOp clip_op = ClipOp::kIntersect, bool is_aa = false) = 0; diff --git a/display_list/dl_op_receiver.h b/display_list/dl_op_receiver.h index dc85e379e4176..8de5dae62c4d7 100644 --- a/display_list/dl_op_receiver.h +++ b/display_list/dl_op_receiver.h @@ -328,7 +328,6 @@ class DlOpReceiver { virtual void transformReset() = 0; virtual void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) = 0; - virtual void clipOval(const SkRect& bounds, ClipOp clip_op, bool is_aa) = 0; virtual void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) = 0; virtual void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) = 0; diff --git a/display_list/dl_op_records.h b/display_list/dl_op_records.h index aeb0379e2371f..3ad6eebe8fc54 100644 --- a/display_list/dl_op_records.h +++ b/display_list/dl_op_records.h @@ -566,11 +566,11 @@ struct TransformResetOp final : TransformClipOpBase { // the header, but the Windows compiler keeps wanting to expand that // packing into more bytes than needed (even when they are declared as // packed bit fields!) -#define DEFINE_CLIP_SHAPE_OP(shapename, shapetype, clipop) \ - struct Clip##clipop##shapename##Op final : TransformClipOpBase { \ - static constexpr auto kType = DisplayListOpType::kClip##clipop##shapename; \ +#define DEFINE_CLIP_SHAPE_OP(shapetype, clipop) \ + struct Clip##clipop##shapetype##Op final : TransformClipOpBase { \ + static constexpr auto kType = DisplayListOpType::kClip##clipop##shapetype; \ \ - Clip##clipop##shapename##Op(Sk##shapetype shape, bool is_aa) \ + Clip##clipop##shapetype##Op(Sk##shapetype shape, bool is_aa) \ : is_aa(is_aa), shape(shape) {} \ \ const bool is_aa; \ @@ -578,17 +578,15 @@ struct TransformResetOp final : TransformClipOpBase { \ void dispatch(DispatchContext& ctx) const { \ if (op_needed(ctx)) { \ - ctx.receiver.clip##shapename(shape, DlCanvas::ClipOp::k##clipop, \ + ctx.receiver.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \ is_aa); \ } \ } \ }; -DEFINE_CLIP_SHAPE_OP(Rect, Rect, Intersect) -DEFINE_CLIP_SHAPE_OP(Oval, Rect, Intersect) -DEFINE_CLIP_SHAPE_OP(RRect, RRect, Intersect) -DEFINE_CLIP_SHAPE_OP(Rect, Rect, Difference) -DEFINE_CLIP_SHAPE_OP(Oval, Rect, Difference) -DEFINE_CLIP_SHAPE_OP(RRect, RRect, Difference) +DEFINE_CLIP_SHAPE_OP(Rect, Intersect) +DEFINE_CLIP_SHAPE_OP(RRect, Intersect) +DEFINE_CLIP_SHAPE_OP(Rect, Difference) +DEFINE_CLIP_SHAPE_OP(RRect, Difference) #undef DEFINE_CLIP_SHAPE_OP #define DEFINE_CLIP_PATH_OP(clipop) \ diff --git a/display_list/skia/dl_sk_canvas.cc b/display_list/skia/dl_sk_canvas.cc index 235b654f41bca..a7334f303ec4b 100644 --- a/display_list/skia/dl_sk_canvas.cc +++ b/display_list/skia/dl_sk_canvas.cc @@ -153,12 +153,6 @@ void DlSkCanvasAdapter::ClipRect(const SkRect& rect, delegate_->clipRect(rect, ToSk(clip_op), is_aa); } -void DlSkCanvasAdapter::ClipOval(const SkRect& bounds, - ClipOp clip_op, - bool is_aa) { - delegate_->clipRRect(SkRRect::MakeOval(bounds), ToSk(clip_op), is_aa); -} - void DlSkCanvasAdapter::ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) { diff --git a/display_list/skia/dl_sk_canvas.h b/display_list/skia/dl_sk_canvas.h index 5ceebe561ef6b..c61f3f465455e 100644 --- a/display_list/skia/dl_sk_canvas.h +++ b/display_list/skia/dl_sk_canvas.h @@ -72,7 +72,6 @@ class DlSkCanvasAdapter final : public virtual DlCanvas { SkMatrix GetTransform() const override; void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; - void ClipOval(const SkRect& bounds, ClipOp clip_op, bool is_aa) override; void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override; diff --git a/display_list/skia/dl_sk_dispatcher.cc b/display_list/skia/dl_sk_dispatcher.cc index 819860d3fb184..84c7115fb5fa4 100644 --- a/display_list/skia/dl_sk_dispatcher.cc +++ b/display_list/skia/dl_sk_dispatcher.cc @@ -122,11 +122,6 @@ void DlSkCanvasDispatcher::clipRect(const SkRect& rect, bool is_aa) { canvas_->clipRect(rect, ToSk(clip_op), is_aa); } -void DlSkCanvasDispatcher::clipOval(const SkRect& bounds, - ClipOp clip_op, - bool is_aa) { - canvas_->clipRRect(SkRRect::MakeOval(bounds), ToSk(clip_op), is_aa); -} void DlSkCanvasDispatcher::clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) { diff --git a/display_list/skia/dl_sk_dispatcher.h b/display_list/skia/dl_sk_dispatcher.h index 384f722633677..ef15f8152e736 100644 --- a/display_list/skia/dl_sk_dispatcher.h +++ b/display_list/skia/dl_sk_dispatcher.h @@ -51,7 +51,6 @@ class DlSkCanvasDispatcher : public virtual DlOpReceiver, void transformReset() override; void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; - void clipOval(const SkRect& bounds, ClipOp clip_op, bool is_aa) override; void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override; diff --git a/display_list/testing/dl_rendering_unittests.cc b/display_list/testing/dl_rendering_unittests.cc index 1368f3e921fbe..89102029e175b 100644 --- a/display_list/testing/dl_rendering_unittests.cc +++ b/display_list/testing/dl_rendering_unittests.cc @@ -2073,39 +2073,6 @@ class CanvasCompareTester { ctx.canvas->ClipRect(r_clip, ClipOp::kDifference, false); }) .with_diff_clip()); - // Skia lacks clipOval and requires us to make an oval SkRRect - SkRRect rr_oval_clip = SkRRect::MakeOval(r_clip); - RenderWith(testP, env, intersect_tolerance, - CaseParameters( - "Hard ClipOval", - [=](const SkSetupContext& ctx) { - ctx.canvas->clipRRect(rr_oval_clip, SkClipOp::kIntersect, - false); - }, - [=](const DlSetupContext& ctx) { - ctx.canvas->ClipOval(r_clip, ClipOp::kIntersect, false); - })); - RenderWith(testP, env, intersect_tolerance, - CaseParameters( - "AntiAlias ClipOval", - [=](const SkSetupContext& ctx) { - ctx.canvas->clipRRect(rr_oval_clip, SkClipOp::kIntersect, - true); - }, - [=](const DlSetupContext& ctx) { - ctx.canvas->ClipOval(r_clip, ClipOp::kIntersect, true); - })); - RenderWith(testP, env, diff_tolerance, - CaseParameters( - "Hard ClipOval Diff", - [=](const SkSetupContext& ctx) { - ctx.canvas->clipRRect(rr_oval_clip, SkClipOp::kDifference, - false); - }, - [=](const DlSetupContext& ctx) { - ctx.canvas->ClipOval(r_clip, ClipOp::kDifference, false); - }) - .with_diff_clip()); // This test RR clip used to use very small radii, but due to // optimizations in the HW rrect rasterization, this caused small // bulges in the corners of the RRect which were interpreted as @@ -2883,14 +2850,12 @@ TEST_F(DisplayListRendering, DrawDiagonalLines) { SkPoint p2 = SkPoint::Make(kRenderRight, kRenderBottom); SkPoint p3 = SkPoint::Make(kRenderLeft, kRenderBottom); SkPoint p4 = SkPoint::Make(kRenderRight, kRenderTop); - // Adding some edge to edge diagonals that run through the points about - // 16 units in from the center of that edge. // Adding some edge center to edge center diagonals to better fill // out the RRect Clip so bounds checking sees less empty bounds space. - SkPoint p5 = SkPoint::Make(kRenderCenterX, kRenderTop + 15); - SkPoint p6 = SkPoint::Make(kRenderRight - 15, kRenderCenterY); - SkPoint p7 = SkPoint::Make(kRenderCenterX, kRenderBottom - 15); - SkPoint p8 = SkPoint::Make(kRenderLeft + 15, kRenderCenterY); + SkPoint p5 = SkPoint::Make(kRenderCenterX, kRenderTop); + SkPoint p6 = SkPoint::Make(kRenderRight, kRenderCenterY); + SkPoint p7 = SkPoint::Make(kRenderLeft, kRenderCenterY); + SkPoint p8 = SkPoint::Make(kRenderCenterX, kRenderBottom); CanvasCompareTester::RenderAll( // TestParameters( @@ -2915,13 +2880,9 @@ TEST_F(DisplayListRendering, DrawDiagonalLines) { .set_draw_line()); } -TEST_F(DisplayListRendering, DrawHorizontalLines) { - SkPoint p1 = SkPoint::Make(kRenderLeft, kRenderTop + 16); - SkPoint p2 = SkPoint::Make(kRenderRight, kRenderTop + 16); - SkPoint p3 = SkPoint::Make(kRenderLeft, kRenderCenterY); - SkPoint p4 = SkPoint::Make(kRenderRight, kRenderCenterY); - SkPoint p5 = SkPoint::Make(kRenderLeft, kRenderBottom - 16); - SkPoint p6 = SkPoint::Make(kRenderRight, kRenderBottom - 16); +TEST_F(DisplayListRendering, DrawHorizontalLine) { + SkPoint p1 = SkPoint::Make(kRenderLeft, kRenderCenterY); + SkPoint p2 = SkPoint::Make(kRenderRight, kRenderCenterY); CanvasCompareTester::RenderAll( // TestParameters( @@ -2932,26 +2893,18 @@ TEST_F(DisplayListRendering, DrawHorizontalLines) { SkPaint p = ctx.paint; p.setStyle(SkPaint::kStroke_Style); ctx.canvas->drawLine(p1, p2, p); - ctx.canvas->drawLine(p3, p4, p); - ctx.canvas->drawLine(p5, p6, p); }, [=](const DlRenderContext& ctx) { // ctx.canvas->DrawLine(p1, p2, ctx.paint); - ctx.canvas->DrawLine(p3, p4, ctx.paint); - ctx.canvas->DrawLine(p5, p6, ctx.paint); }, kDrawHVLineFlags) .set_draw_line() .set_horizontal_line()); } -TEST_F(DisplayListRendering, DrawVerticalLines) { - SkPoint p1 = SkPoint::Make(kRenderLeft + 16, kRenderTop); - SkPoint p2 = SkPoint::Make(kRenderLeft + 16, kRenderBottom); - SkPoint p3 = SkPoint::Make(kRenderCenterX, kRenderTop); - SkPoint p4 = SkPoint::Make(kRenderCenterX, kRenderBottom); - SkPoint p5 = SkPoint::Make(kRenderRight - 16, kRenderTop); - SkPoint p6 = SkPoint::Make(kRenderRight - 16, kRenderBottom); +TEST_F(DisplayListRendering, DrawVerticalLine) { + SkPoint p1 = SkPoint::Make(kRenderCenterX, kRenderTop); + SkPoint p2 = SkPoint::Make(kRenderCenterY, kRenderBottom); CanvasCompareTester::RenderAll( // TestParameters( @@ -2962,13 +2915,9 @@ TEST_F(DisplayListRendering, DrawVerticalLines) { SkPaint p = ctx.paint; p.setStyle(SkPaint::kStroke_Style); ctx.canvas->drawLine(p1, p2, p); - ctx.canvas->drawLine(p3, p4, p); - ctx.canvas->drawLine(p5, p6, p); }, [=](const DlRenderContext& ctx) { // ctx.canvas->DrawLine(p1, p2, ctx.paint); - ctx.canvas->DrawLine(p3, p4, ctx.paint); - ctx.canvas->DrawLine(p5, p6, ctx.paint); }, kDrawHVLineFlags) .set_draw_line() @@ -2980,14 +2929,12 @@ TEST_F(DisplayListRendering, DrawDiagonalDashedLines) { SkPoint p2 = SkPoint::Make(kRenderRight, kRenderBottom); SkPoint p3 = SkPoint::Make(kRenderLeft, kRenderBottom); SkPoint p4 = SkPoint::Make(kRenderRight, kRenderTop); - // Adding some edge to edge diagonals that run through the points about - // 16 units in from the center of that edge. // Adding some edge center to edge center diagonals to better fill // out the RRect Clip so bounds checking sees less empty bounds space. - SkPoint p5 = SkPoint::Make(kRenderCenterX, kRenderTop + 15); - SkPoint p6 = SkPoint::Make(kRenderRight - 15, kRenderCenterY); - SkPoint p7 = SkPoint::Make(kRenderCenterX, kRenderBottom - 15); - SkPoint p8 = SkPoint::Make(kRenderLeft + 15, kRenderCenterY); + SkPoint p5 = SkPoint::Make(kRenderCenterX, kRenderTop); + SkPoint p6 = SkPoint::Make(kRenderRight, kRenderCenterY); + SkPoint p7 = SkPoint::Make(kRenderLeft, kRenderCenterY); + SkPoint p8 = SkPoint::Make(kRenderCenterX, kRenderBottom); // Full diagonals are 100x100 which are 140 in length // Dashing them with 25 on, 5 off means that the last @@ -3008,7 +2955,7 @@ TEST_F(DisplayListRendering, DrawDiagonalDashedLines) { SkPaint p = ctx.paint; p.setStyle(SkPaint::kStroke_Style); SkScalar intervals[2] = {25.0f, 5.0f}; - p.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0.0f)); + p.setPathEffect(SkDashPathEffect::Make(intervals, 2.0f, 0.0f)); ctx.canvas->drawLine(p1, p2, p); ctx.canvas->drawLine(p3, p4, p); ctx.canvas->drawLine(p5, p6, p); @@ -3178,7 +3125,7 @@ TEST_F(DisplayListRendering, DrawPointsAsPoints) { const SkScalar x3 = kRenderCenterX + 0.1; const SkScalar x4 = (kRenderRight + kRenderCenterX) * 0.5; const SkScalar x5 = kRenderRight - 16; - const SkScalar x6 = kRenderRight - 1; + const SkScalar x6 = kRenderRight; const SkScalar y0 = kRenderTop; const SkScalar y1 = kRenderTop + 16; @@ -3186,7 +3133,7 @@ TEST_F(DisplayListRendering, DrawPointsAsPoints) { const SkScalar y3 = kRenderCenterY + 0.1; const SkScalar y4 = (kRenderBottom + kRenderCenterY) * 0.5; const SkScalar y5 = kRenderBottom - 16; - const SkScalar y6 = kRenderBottom - 1; + const SkScalar y6 = kRenderBottom; // clang-format off const SkPoint points[] = { @@ -3230,7 +3177,7 @@ TEST_F(DisplayListRendering, DrawPointsAsLines) { const SkScalar y0 = kRenderTop; const SkScalar y1 = kRenderTop + 16; const SkScalar y2 = kRenderBottom - 16; - const SkScalar y3 = kRenderBottom - 1; + const SkScalar y3 = kRenderBottom; // clang-format off const SkPoint points[] = { @@ -3279,12 +3226,10 @@ TEST_F(DisplayListRendering, DrawPointsAsPolygon) { SkPoint::Make(kRenderRight, kRenderBottom), SkPoint::Make(kRenderLeft, kRenderBottom), SkPoint::Make(kRenderLeft, kRenderTop), - - SkPoint::Make(kRenderCenterX, kRenderTop + 15), - SkPoint::Make(kRenderRight - 15, kRenderCenterY), - SkPoint::Make(kRenderCenterX, kRenderBottom - 15), - SkPoint::Make(kRenderLeft + 15, kRenderCenterY), - SkPoint::Make(kRenderCenterX, kRenderTop + 15), + SkPoint::Make(kRenderCenterX, kRenderTop), + SkPoint::Make(kRenderRight, kRenderCenterY), + SkPoint::Make(kRenderCenterX, kRenderBottom), + SkPoint::Make(kRenderLeft, kRenderCenterY), }; const int count1 = sizeof(points1) / sizeof(points1[0]); @@ -3785,7 +3730,7 @@ TEST_F(DisplayListRendering, DrawShadow) { }, kRenderCornerRadius, kRenderCornerRadius); const DlColor color = DlColor::kDarkGrey(); - const SkScalar elevation = 7; + const SkScalar elevation = 5; CanvasCompareTester::RenderAll( // TestParameters( @@ -3811,7 +3756,7 @@ TEST_F(DisplayListRendering, DrawShadowTransparentOccluder) { }, kRenderCornerRadius, kRenderCornerRadius); const DlColor color = DlColor::kDarkGrey(); - const SkScalar elevation = 7; + const SkScalar elevation = 5; CanvasCompareTester::RenderAll( // TestParameters( @@ -3837,7 +3782,7 @@ TEST_F(DisplayListRendering, DrawShadowDpr) { }, kRenderCornerRadius, kRenderCornerRadius); const DlColor color = DlColor::kDarkGrey(); - const SkScalar elevation = 7; + const SkScalar elevation = 5; CanvasCompareTester::RenderAll( // TestParameters( diff --git a/display_list/testing/dl_test_snippets.cc b/display_list/testing/dl_test_snippets.cc index 16c0edb5d4468..e5ad4b2f365dc 100644 --- a/display_list/testing/dl_test_snippets.cc +++ b/display_list/testing/dl_test_snippets.cc @@ -424,30 +424,6 @@ std::vector CreateAllClipOps() { r.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, false); }}, }}, - {"ClipOval", - { - {1, 24, 0, - [](DlOpReceiver& r) { - r.clipOval(kTestBounds, DlCanvas::ClipOp::kIntersect, true); - }}, - {1, 24, 0, - [](DlOpReceiver& r) { - r.clipOval(kTestBounds.makeOffset(1, 1), - DlCanvas::ClipOp::kIntersect, true); - }}, - {1, 24, 0, - [](DlOpReceiver& r) { - r.clipOval(kTestBounds, DlCanvas::ClipOp::kIntersect, false); - }}, - {1, 24, 0, - [](DlOpReceiver& r) { - r.clipOval(kTestBounds, DlCanvas::ClipOp::kDifference, true); - }}, - {1, 24, 0, - [](DlOpReceiver& r) { - r.clipOval(kTestBounds, DlCanvas::ClipOp::kDifference, false); - }}, - }}, {"ClipRRect", { {1, 64, 0, @@ -503,15 +479,10 @@ std::vector CreateAllClipOps() { [](DlOpReceiver& r) { r.clipPath(kTestPathRect, DlCanvas::ClipOp::kIntersect, true); }}, - // clipPath(oval) becomes clipOval - {1, 24, 0, - [](DlOpReceiver& r) { - r.clipPath(kTestPathOval, DlCanvas::ClipOp::kIntersect, true); - }}, - // clipPath(rrect) becomes clipRRect + // clipPath(oval) becomes clipRRect {1, 64, 0, [](DlOpReceiver& r) { - r.clipPath(kTestPathRRect, DlCanvas::ClipOp::kIntersect, true); + r.clipPath(kTestPathOval, DlCanvas::ClipOp::kIntersect, true); }}, }}, }; @@ -666,11 +637,8 @@ std::vector CreateAllRenderingOps() { {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPath1); }}, {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPath2); }}, {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPath3); }}, - // oval and rect paths are redirected to drawRect and drawOval - {1, 24, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathRect); }}, - {1, 24, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathOval); }}, - // rrect path is redirected to drawRRect - {1, 56, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathRRect); }}, + {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathRect); }}, + {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathOval); }}, }}, {"DrawArc", { diff --git a/display_list/testing/dl_test_snippets.h b/display_list/testing/dl_test_snippets.h index 733ce67364034..16d740c2fb6a0 100644 --- a/display_list/testing/dl_test_snippets.h +++ b/display_list/testing/dl_test_snippets.h @@ -183,7 +183,6 @@ static const SkRRect kTestInnerRRect = SkRRect::MakeRectXY(kTestBounds.makeInset(5, 5), 2, 2); static const SkPath kTestPathRect = SkPath::Rect(kTestBounds); static const SkPath kTestPathOval = SkPath::Oval(kTestBounds); -static const SkPath kTestPathRRect = SkPath::RRect(kTestRRect); static const SkPath kTestPath1 = SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true); static const SkPath kTestPath2 = diff --git a/display_list/utils/dl_matrix_clip_tracker.cc b/display_list/utils/dl_matrix_clip_tracker.cc index 86f3cff46a6d9..748cf07a8385a 100644 --- a/display_list/utils/dl_matrix_clip_tracker.cc +++ b/display_list/utils/dl_matrix_clip_tracker.cc @@ -74,24 +74,6 @@ void DisplayListMatrixClipState::clipRect(const DlRect& rect, } } -void DisplayListMatrixClipState::clipOval(const DlRect& bounds, - ClipOp op, - bool is_aa) { - if (!bounds.IsFinite()) { - return; - } - switch (op) { - case DlCanvas::ClipOp::kIntersect: - adjustCullRect(bounds, op, is_aa); - break; - case DlCanvas::ClipOp::kDifference: - if (oval_covers_cull(bounds)) { - cull_rect_ = DlRect(); - } - break; - } -} - void DisplayListMatrixClipState::clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) { diff --git a/display_list/utils/dl_matrix_clip_tracker.h b/display_list/utils/dl_matrix_clip_tracker.h index 4a6198d75a3e1..59c9880bd3bd7 100644 --- a/display_list/utils/dl_matrix_clip_tracker.h +++ b/display_list/utils/dl_matrix_clip_tracker.h @@ -149,10 +149,6 @@ class DisplayListMatrixClipState { void clipRect(const SkRect& rect, ClipOp op, bool is_aa) { clipRect(ToDlRect(rect), op, is_aa); } - void clipOval(const DlRect& bounds, ClipOp op, bool is_aa); - void clipOval(const SkRect& bounds, ClipOp op, bool is_aa) { - clipRect(ToDlRect(bounds), op, is_aa); - } void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa); void clipPath(const SkPath& path, ClipOp op, bool is_aa); diff --git a/display_list/utils/dl_receiver_utils.h b/display_list/utils/dl_receiver_utils.h index bb6ce6539f653..d50cb00cba057 100644 --- a/display_list/utils/dl_receiver_utils.h +++ b/display_list/utils/dl_receiver_utils.h @@ -44,9 +44,6 @@ class IgnoreClipDispatchHelper : public virtual DlOpReceiver { void clipRect(const SkRect& rect, DlCanvas::ClipOp clip_op, bool is_aa) override {} - void clipOval(const SkRect& bounds, - DlCanvas::ClipOp clip_op, - bool is_aa) override {} void clipRRect(const SkRRect& rrect, DlCanvas::ClipOp clip_op, bool is_aa) override {} diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 1525d9f9087d7..cdf59f42a58ad 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -1246,6 +1246,32 @@ TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, FastEllipticalRRectMaskBlursRenderCorrectly) { + Canvas canvas; + canvas.Scale(GetContentScale()); + Paint paint; + paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{ + .style = FilterContents::BlurStyle::kNormal, + .sigma = Sigma{1}, + }; + + canvas.DrawPaint({.color = Color::White()}); + + paint.color = Color::Blue(); + for (int i = 0; i < 5; i++) { + Scalar y = i * 125; + Scalar y_radius = i * 15; + for (int j = 0; j < 5; j++) { + Scalar x = j * 125; + Scalar x_radius = j * 15; + canvas.DrawRRect(Rect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), + {x_radius, y_radius}, paint); + } + } + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) { Canvas canvas; canvas.Scale(GetContentScale()); diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 2a2bfb2f78609..f1b6552b34c97 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -723,14 +723,6 @@ void DlDispatcherBase::clipRect(const SkRect& rect, ToClipOperation(clip_op)); } -// |flutter::DlOpReceiver| -void DlDispatcherBase::clipOval(const SkRect& bounds, - ClipOp clip_op, - bool is_aa) { - GetCanvas().ClipOval(skia_conversions::ToRect(bounds), - ToClipOperation(clip_op)); -} - // |flutter::DlOpReceiver| void DlDispatcherBase::clipRRect(const SkRRect& rrect, ClipOp sk_op, diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h index 294616b748776..7349ca7e4fd84 100644 --- a/impeller/display_list/dl_dispatcher.h +++ b/impeller/display_list/dl_dispatcher.h @@ -123,9 +123,6 @@ class DlDispatcherBase : public flutter::DlOpReceiver { // |flutter::DlOpReceiver| void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; - // |flutter::DlOpReceiver| - void clipOval(const SkRect& bounds, ClipOp clip_op, bool is_aa) override; - // |flutter::DlOpReceiver| void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; diff --git a/impeller/entity/contents/solid_rrect_blur_contents.cc b/impeller/entity/contents/solid_rrect_blur_contents.cc index b6bdffd2b7d81..4f62435a02dad 100644 --- a/impeller/entity/contents/solid_rrect_blur_contents.cc +++ b/impeller/entity/contents/solid_rrect_blur_contents.cc @@ -113,7 +113,7 @@ bool SolidRRectBlurContents::Render(const ContentContext& renderer, frag_info.rect_size = Point(positive_rect.GetSize()); frag_info.corner_radii = {std::clamp(corner_radii_.width, kEhCloseEnough, positive_rect.GetWidth() * 0.5f), - std::clamp(corner_radii_.width, kEhCloseEnough, + std::clamp(corner_radii_.height, kEhCloseEnough, positive_rect.GetHeight() * 0.5f)}; pass.SetCommandLabel("RRect Shadow"); diff --git a/impeller/renderer/backend/metal/allocator_mtl.mm b/impeller/renderer/backend/metal/allocator_mtl.mm index 913f7333205a8..6a9e4437f4bb5 100644 --- a/impeller/renderer/backend/metal/allocator_mtl.mm +++ b/impeller/renderer/backend/metal/allocator_mtl.mm @@ -99,7 +99,8 @@ static bool SupportsLossyTextureCompression(id device) { } size_t DebugAllocatorStats::GetAllocationSizeMB() { - size_t new_value = size_ / 1000000; + // RAM is measured in MiB, thus a divisor of 2^20 instead of 1,000,000. + size_t new_value = size_ / (1024 * 1024); return new_value; } diff --git a/impeller/renderer/backend/metal/allocator_mtl_unittests.mm b/impeller/renderer/backend/metal/allocator_mtl_unittests.mm index 4150caf20ce9d..ea1bac5421b67 100644 --- a/impeller/renderer/backend/metal/allocator_mtl_unittests.mm +++ b/impeller/renderer/backend/metal/allocator_mtl_unittests.mm @@ -36,7 +36,7 @@ TextureDescriptor desc; desc.format = PixelFormat::kR8G8B8A8UNormInt; desc.storage_mode = StorageMode::kDeviceTransient; - desc.size = {1000, 1000}; + desc.size = {1024, 1024}; auto texture_1 = allocator->CreateTexture(desc); EXPECT_EQ(allocator->DebugGetHeapUsage(), 0u); diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc index 364b9aa49afbd..032f9d7e7d51b 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -519,7 +519,7 @@ size_t AllocatorVK::DebugGetHeapUsage() const { total_usage += budget.usage; } // Convert bytes to MB. - total_usage *= 1e-6; + total_usage /= (1024 * 1024); return total_usage; } diff --git a/lib/ui/semantics.dart b/lib/ui/semantics.dart index 481c9c3cbc525..57bc1fa30726d 100644 --- a/lib/ui/semantics.dart +++ b/lib/ui/semantics.dart @@ -220,9 +220,6 @@ class SemanticsAction { /// must immediately become editable, opening a virtual keyboard, if needed. /// Buttons must respond to tap/click events from the keyboard. /// - /// Widget reaction to this action must be idempotent. It is possible to - /// receive this action more than once, or when the widget is already focused. - /// /// Focus behavior is specific to the platform and to the assistive technology /// used. Typically on desktop operating systems, such as Windows, macOS, and /// Linux, moving accessibility focus will also move the input focus. On diff --git a/lib/web_ui/flutter_js/src/canvaskit_loader.js b/lib/web_ui/flutter_js/src/canvaskit_loader.js index 4c8e91c7bc175..64dc6734ec273 100644 --- a/lib/web_ui/flutter_js/src/canvaskit_loader.js +++ b/lib/web_ui/flutter_js/src/canvaskit_loader.js @@ -6,11 +6,11 @@ import { createWasmInstantiator } from "./instantiate_wasm.js"; import { joinPathSegments } from "./utils.js"; export const loadCanvasKit = (deps, config, browserEnvironment, canvasKitBaseUrl) => { - window.flutterCanvasKitLoaded = (async () => { - if (window.flutterCanvasKit) { - // The user has set this global variable ahead of time, so we just return that. - return window.flutterCanvasKit; - } + if (window.flutterCanvasKit) { + // The user has set this global variable ahead of time, so we just return that. + return Promise.resolve(window.flutterCanvasKit); + } + window.flutterCanvasKitLoaded = new Promise((resolve, reject) => { const supportsChromiumCanvasKit = browserEnvironment.hasChromiumBreakIterators && browserEnvironment.hasImageCodecs; if (!supportsChromiumCanvasKit && config.canvasKitVariant == "chromium") { throw "Chromium CanvasKit variant specifically requested, but unsupported in this browser"; @@ -25,11 +25,24 @@ export const loadCanvasKit = (deps, config, browserEnvironment, canvasKitBaseUrl canvasKitUrl = deps.flutterTT.policy.createScriptURL(canvasKitUrl); } const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "canvaskit.wasm")); - const canvasKitModule = await import(canvasKitUrl); - window.flutterCanvasKit = await canvasKitModule.default({ - instantiateWasm: wasmInstantiator, + const script = document.createElement("script"); + script.src = canvasKitUrl; + if (config.nonce) { + script.nonce = config.nonce; + } + script.addEventListener("load", async () => { + try { + const canvasKit = await CanvasKitInit({ + instantiateWasm: wasmInstantiator, + }); + window.flutterCanvasKit = canvasKit; + resolve(canvasKit); + } catch (e) { + reject(e); + } }); - return window.flutterCanvasKit; - })(); + script.addEventListener("error", reject); + document.head.appendChild(script); + }); return window.flutterCanvasKitLoaded; } diff --git a/lib/web_ui/flutter_js/src/skwasm_loader.js b/lib/web_ui/flutter_js/src/skwasm_loader.js index 01b4fe3cb2375..241f4e8c81e02 100644 --- a/lib/web_ui/flutter_js/src/skwasm_loader.js +++ b/lib/web_ui/flutter_js/src/skwasm_loader.js @@ -5,28 +5,43 @@ import { createWasmInstantiator } from "./instantiate_wasm.js"; import { joinPathSegments } from "./utils.js"; -export const loadSkwasm = async (deps, config, browserEnvironment, baseUrl) => { - let skwasmUrl = joinPathSegments(baseUrl, "skwasm.js"); - if (deps.flutterTT.policy) { - skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl); - } - const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "skwasm.wasm")); - const skwasm = await import(skwasmUrl); - return await skwasm.default({ - instantiateWasm: wasmInstantiator, - locateFile: (fileName, scriptDirectory) => { - // When hosted via a CDN or some other url that is not the same - // origin as the main script of the page, we will fail to create - // a web worker with the .worker.js script. This workaround will - // make sure that the worker JS can be loaded regardless of where - // it is hosted. - const url = scriptDirectory + fileName; - if (url.endsWith('.worker.js')) { - return URL.createObjectURL(new Blob( - [`importScripts('${url}');`], - { 'type': 'application/javascript' })); - } - return url; +export const loadSkwasm = (deps, config, browserEnvironment, baseUrl) => { + return new Promise((resolve, reject) => { + let skwasmUrl = joinPathSegments(baseUrl, "skwasm.js"); + if (deps.flutterTT.policy) { + skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl); + } + const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "skwasm.wasm")); + const script = document.createElement("script"); + script.src = skwasmUrl; + if (config.nonce) { + script.nonce = config.nonce; } + script.addEventListener("load", async () => { + try { + const skwasmInstance = await skwasm({ + instantiateWasm: wasmInstantiator, + locateFile: (fileName, scriptDirectory) => { + // When hosted via a CDN or some other url that is not the same + // origin as the main script of the page, we will fail to create + // a web worker with the .worker.js script. This workaround will + // make sure that the worker JS can be loaded regardless of where + // it is hosted. + const url = scriptDirectory + fileName; + if (url.endsWith(".worker.js")) { + return URL.createObjectURL(new Blob( + [`importScripts("${url}");`], + { "type": "application/javascript" })); + } + return url; + } + }); + resolve(skwasmInstance); + } catch (e) { + reject(e); + } + }); + script.addEventListener("error", reject); + document.head.appendChild(script); }); } diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart index 2e6e8dfc62a6e..c41da41b36aac 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart @@ -259,13 +259,12 @@ extension CanvasKitExtension on CanvasKit { ); } -@JS() -@staticInterop -class CanvasKitModule {} +@JS('window.CanvasKitInit') +external JSAny _CanvasKitInit(CanvasKitInitOptions options); -extension CanvasKitModuleExtension on CanvasKitModule { - @JS('default') - external JSPromise defaultExport(CanvasKitInitOptions options); +Future CanvasKitInit(CanvasKitInitOptions options) { + return js_util.promiseToFuture( + _CanvasKitInit(options).toObjectShallow); } typedef LocateFileCallback = String Function(String file, String unusedBase); @@ -3662,11 +3661,11 @@ String canvasKitWasmModuleUrl(String file, String canvasKitBase) => /// Downloads the CanvasKit JavaScript, then calls `CanvasKitInit` to download /// and intialize the CanvasKit wasm. Future downloadCanvasKit() async { - final CanvasKitModule canvasKitModule = await _downloadOneOf(_canvasKitJsUrls); + await _downloadOneOf(_canvasKitJsUrls); - final CanvasKit canvasKit = (await canvasKitModule.defaultExport(CanvasKitInitOptions( + final CanvasKit canvasKit = await CanvasKitInit(CanvasKitInitOptions( locateFile: createLocateFileCallback(canvasKitWasmModuleUrl), - )).toDart) as CanvasKit; + )); if (canvasKit.ParagraphBuilder.RequiresClientICU() && !browserSupportsCanvaskitChromium) { throw Exception( @@ -3682,12 +3681,10 @@ Future downloadCanvasKit() async { /// downloads it. /// /// If none of the URLs can be downloaded, throws an [Exception]. -Future _downloadOneOf(Iterable urls) async { +Future _downloadOneOf(Iterable urls) async { for (final String url in urls) { - try { - return await _downloadCanvasKitJs(url); - } catch (_) { - continue; + if (await _downloadCanvasKitJs(url)) { + return; } } @@ -3701,7 +3698,32 @@ Future _downloadOneOf(Iterable urls) async { /// /// Returns a [Future] that completes with `true` if the CanvasKit JavaScript /// file was successfully downloaded, or `false` if it failed. -Future _downloadCanvasKitJs(String url) async { - final JSAny scriptUrl = createTrustedScriptUrl(url); - return (await importModule(scriptUrl).toDart) as CanvasKitModule; +Future _downloadCanvasKitJs(String url) { + final DomHTMLScriptElement canvasKitScript = + createDomHTMLScriptElement(configuration.nonce); + canvasKitScript.src = createTrustedScriptUrl(url); + + final Completer canvasKitLoadCompleter = Completer(); + + late final DomEventListener loadCallback; + late final DomEventListener errorCallback; + + void loadEventHandler(DomEvent _) { + canvasKitScript.remove(); + canvasKitLoadCompleter.complete(true); + } + void errorEventHandler(DomEvent errorEvent) { + canvasKitScript.remove(); + canvasKitLoadCompleter.complete(false); + } + + loadCallback = createDomEventListener(loadEventHandler); + errorCallback = createDomEventListener(errorEventHandler); + + canvasKitScript.addEventListener('load', loadCallback); + canvasKitScript.addEventListener('error', errorCallback); + + domDocument.head!.appendChild(canvasKitScript); + + return canvasKitLoadCompleter.future; } diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart index 14bde5e5def70..b81bba41245f2 100644 --- a/lib/web_ui/lib/src/engine/dom.dart +++ b/lib/web_ui/lib/src/engine/dom.dart @@ -2753,30 +2753,6 @@ DomCompositionEvent createDomCompositionEvent(String type, } } -/// This is a pseudo-type for DOM elements that have the boolean `disabled` -/// property. -/// -/// This type cannot be part of the actual type hierarchy because each DOM type -/// defines its `disabled` property ad hoc, without inheriting it from a common -/// type, e.g. [DomHTMLInputElement] and [DomHTMLTextAreaElement]. -/// -/// To use, simply cast any element known to have the `disabled` property to -/// this type using `as DomElementWithDisabledProperty`, then read and write -/// this property as normal. -@JS() -@staticInterop -class DomElementWithDisabledProperty extends DomHTMLElement {} - -extension DomElementWithDisabledPropertyExtension on DomElementWithDisabledProperty { - @JS('disabled') - external JSBoolean? get _disabled; - bool? get disabled => _disabled?.toDart; - - @JS('disabled') - external set _disabled(JSBoolean? value); - set disabled(bool? value) => _disabled = value?.toJS; -} - @JS() @staticInterop class DomHTMLInputElement extends DomHTMLElement {} @@ -3407,16 +3383,16 @@ final DomTrustedTypePolicy _ttPolicy = domWindow.trustedTypes!.createPolicy( /// Converts a String `url` into a [DomTrustedScriptURL] object when the /// Trusted Types API is available, else returns the unmodified `url`. -JSAny createTrustedScriptUrl(String url) { +Object createTrustedScriptUrl(String url) { if (domWindow.trustedTypes != null) { // Pass `url` through Flutter Engine's TrustedType policy. final DomTrustedScriptURL trustedUrl = _ttPolicy.createScriptURL(url); assert(trustedUrl.url != '', 'URL: $url rejected by TrustedTypePolicy'); - return trustedUrl as JSAny; + return trustedUrl; } - return url.toJS; + return url; } DomMessageChannel createDomMessageChannel() => DomMessageChannel(); diff --git a/lib/web_ui/lib/src/engine/semantics/focusable.dart b/lib/web_ui/lib/src/engine/semantics/focusable.dart index 331e1cd50c061..35fff64a50158 100644 --- a/lib/web_ui/lib/src/engine/semantics/focusable.dart +++ b/lib/web_ui/lib/src/engine/semantics/focusable.dart @@ -81,6 +81,9 @@ typedef _FocusTarget = ({ /// The listener for the "focus" DOM event. DomEventListener domFocusListener, + + /// The listener for the "blur" DOM event. + DomEventListener domBlurListener, }); /// Implements accessibility focus management for arbitrary elements. @@ -132,6 +135,7 @@ class AccessibilityFocusManager { semanticsNodeId: semanticsNodeId, element: previousTarget.element, domFocusListener: previousTarget.domFocusListener, + domBlurListener: previousTarget.domBlurListener, ); return; } @@ -144,12 +148,14 @@ class AccessibilityFocusManager { final _FocusTarget newTarget = ( semanticsNodeId: semanticsNodeId, element: element, - domFocusListener: createDomEventListener((_) => _didReceiveDomFocus()), + domFocusListener: createDomEventListener((_) => _setFocusFromDom(true)), + domBlurListener: createDomEventListener((_) => _setFocusFromDom(false)), ); _target = newTarget; element.tabIndex = 0; element.addEventListener('focus', newTarget.domFocusListener); + element.addEventListener('blur', newTarget.domBlurListener); } /// Stops managing the focus of the current element, if any. @@ -164,9 +170,10 @@ class AccessibilityFocusManager { } target.element.removeEventListener('focus', target.domFocusListener); + target.element.removeEventListener('blur', target.domBlurListener); } - void _didReceiveDomFocus() { + void _setFocusFromDom(bool acquireFocus) { final _FocusTarget? target = _target; if (target == null) { @@ -177,7 +184,9 @@ class AccessibilityFocusManager { EnginePlatformDispatcher.instance.invokeOnSemanticsAction( target.semanticsNodeId, - ui.SemanticsAction.focus, + acquireFocus + ? ui.SemanticsAction.didGainAccessibilityFocus + : ui.SemanticsAction.didLoseAccessibilityFocus, null, ); } @@ -220,7 +229,7 @@ class AccessibilityFocusManager { // a dialog, and nothing else in the dialog is focused. The Flutter // framework expects that the screen reader will focus on the first (in // traversal order) focusable element inside the dialog and send a - // SemanticsAction.focus action. Screen readers on the web do not do + // didGainAccessibilityFocus action. Screen readers on the web do not do // that, and so the web engine has to implement this behavior directly. So // the dialog will look for a focusable element and request focus on it, // but now there may be a race between this method unsetting the focus and diff --git a/lib/web_ui/lib/src/engine/semantics/semantics.dart b/lib/web_ui/lib/src/engine/semantics/semantics.dart index 0918ef49c3ff7..c48851d9836a2 100644 --- a/lib/web_ui/lib/src/engine/semantics/semantics.dart +++ b/lib/web_ui/lib/src/engine/semantics/semantics.dart @@ -2218,6 +2218,8 @@ class EngineSemantics { 'mousemove', 'mouseleave', 'mouseup', + 'keyup', + 'keydown', ]; if (pointerEventTypes.contains(event.type)) { diff --git a/lib/web_ui/lib/src/engine/semantics/text_field.dart b/lib/web_ui/lib/src/engine/semantics/text_field.dart index 3618306d37829..bb79ea1df52d9 100644 --- a/lib/web_ui/lib/src/engine/semantics/text_field.dart +++ b/lib/web_ui/lib/src/engine/semantics/text_field.dart @@ -2,8 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; import 'package:ui/ui.dart' as ui; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; +import '../browser_detection.dart' show isIosSafari; import '../dom.dart'; import '../platform_dispatcher.dart'; import '../text_editing/text_editing.dart'; @@ -120,10 +123,7 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy { // Android). // Otherwise, the keyboard stays on screen even when the user navigates to // a different screen (e.g. by hitting the "back" button). - // Keep this consistent with how DefaultTextEditingStrategy does it. As of - // right now, the only difference is that semantic text fields do not - // participate in form autofill. - DefaultTextEditingStrategy.scheduleFocusFlutterView(activeDomElement, activeDomElementView); + domElement?.blur(); domElement = null; activeTextField = null; _queuedStyle = null; @@ -162,7 +162,7 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy { if (hasAutofillGroup) { placeForm(); } - activeDomElement.focus(preventScroll: true); + activeDomElement.focus(); } @override @@ -207,40 +207,69 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy { /// [EngineSemanticsOwner.gestureMode]. However, in Chrome on Android it ignores /// browser gestures when in pointer mode. In Safari on iOS pointer events are /// used to detect text box invocation. This is because Safari issues touch -/// events even when VoiceOver is enabled. +/// events even when Voiceover is enabled. class TextField extends PrimaryRoleManager { TextField(SemanticsObject semanticsObject) : super.blank(PrimaryRole.textField, semanticsObject) { - _initializeEditableElement(); + _setupDomElement(); } - /// The element used for editing, e.g. ``, `