respect reversed scroll views (#39195)

This PR makes Scrollable scroll in correct direction when reverse: true on desktop and web
diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart
index e6b9567..f3e9ebb 100644
--- a/packages/flutter/lib/src/widgets/scrollable.dart
+++ b/packages/flutter/lib/src/widgets/scrollable.dart
@@ -9,6 +9,7 @@
 import 'package:flutter/gestures.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/scheduler.dart';
+import 'package:flutter/painting.dart';
 
 import 'basic.dart';
 import 'framework.dart';
@@ -528,9 +529,14 @@
   // Returns the offset that should result from applying [event] to the current
   // position, taking min/max scroll extent into account.
   double _targetScrollOffsetForPointerScroll(PointerScrollEvent event) {
-    final double delta = widget.axis == Axis.horizontal
+    double delta = widget.axis == Axis.horizontal
         ? event.scrollDelta.dx
         : event.scrollDelta.dy;
+
+    if (axisDirectionIsReversed(widget.axisDirection)) {
+      delta *= -1;
+    }
+
     return math.min(math.max(position.pixels + delta, position.minScrollExtent),
         position.maxScrollExtent);
   }
diff --git a/packages/flutter/test/widgets/scrollable_test.dart b/packages/flutter/test/widgets/scrollable_test.dart
index ac14564..b9a3183 100644
--- a/packages/flutter/test/widgets/scrollable_test.dart
+++ b/packages/flutter/test/widgets/scrollable_test.dart
@@ -8,12 +8,18 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 
-Future<void> pumpTest(WidgetTester tester, TargetPlatform platform, {bool scrollable = true}) async {
+Future<void> pumpTest(
+  WidgetTester tester,
+  TargetPlatform platform, {
+  bool scrollable = true,
+  bool reverse = false,
+}) async {
   await tester.pumpWidget(MaterialApp(
     theme: ThemeData(
       platform: platform,
     ),
     home: CustomScrollView(
+      reverse: reverse,
       physics: scrollable ? null : const NeverScrollableScrollPhysics(),
       slivers: const <Widget>[
         SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
@@ -248,4 +254,17 @@
     await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)), result);
     expect(getScrollOffset(tester), 0.0);
   });
+
+  testWidgets('Scrolls in correct direction when scroll axis is reversed', (WidgetTester tester) async {
+    await pumpTest(tester, TargetPlatform.fuchsia, reverse: true);
+
+    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
+    final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
+    // Create a hover event so that |testPointer| has a location when generating the scroll.
+    testPointer.hover(scrollEventLocation);
+    final HitTestResult result = tester.hitTestOnBinding(scrollEventLocation);
+    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, -20.0)), result);
+
+    expect(getScrollOffset(tester), 20.0);
+  });
 }