Export the Skia ShadowMaskFilter API (#3401)

See https://github.com/flutter/flutter/issues/6807
diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart
index 0347e57..9f85998 100644
--- a/lib/ui/painting.dart
+++ b/lib/ui/painting.dart
@@ -861,9 +861,49 @@
   ///
   /// A blur is an expensive operation and should therefore be used sparingly.
   MaskFilter.blur(BlurStyle style, double sigma) {
-    _constructor(style.index, sigma);
+    _constructorBlur(style.index, sigma);
   }
-  void _constructor(int style, double sigma) native "MaskFilter_constructor";
+  void _constructorBlur(int style, double sigma) native "MaskFilter_constructorBlur";
+
+  /// Creates a mask filter that implements a pair of shadows for an occluding
+  /// object - one representing ambient occlusion, and one representing a
+  /// displaced shadow from a point light.
+  ///
+  /// `occluderHeight`: Height of occluding object off of ground plane.
+  ///
+  /// `lightPos`: Position of the light applied to this object.
+  ///
+  /// `lightRadius`: Radius of the light (light is assumed to be spherical).
+  ///
+  /// `ambientAlpha`: Base opacity of the ambient occlusion shadow.
+  ///
+  /// `spotAlpha`: Base opacity of the displaced spot shadow.
+  MaskFilter.shadow({
+    double occluderHeight: 0.0,
+    double lightPosX: 0.0,
+    double lightPosY: 0.0,
+    double lightPosZ: 0.0,
+    double lightRadius: 0.0,
+    double ambientAlpha: 0.0,
+    double spotAlpha: 0.0,
+  }) {
+    if (!(occluderHeight > 0.0 &&
+          lightPosZ > occluderHeight &&
+          lightRadius > 0.0 &&
+          ambientAlpha >= 0.0 &&
+          spotAlpha >= 0.0))
+      throw new ArgumentError("Invalid shadow mask filter parameters");
+
+    _constructorShadow(occluderHeight, lightPosX, lightPosY, lightPosZ,
+                       lightRadius, ambientAlpha, spotAlpha);
+  }
+  void _constructorShadow(double occluderHeight,
+                          double lightPosX,
+                          double lightPosY,
+                          double lightPosZ,
+                          double lightRadius,
+                          double ambientAlpha,
+                          double spotAlpha) native "MaskFilter_constructorShadow";
 }
 
 /// A description of a color filter to apply when drawing a shape or compositing
diff --git a/lib/ui/painting/mask_filter.cc b/lib/ui/painting/mask_filter.cc
index 0e6866a..26a7fc6 100644
--- a/lib/ui/painting/mask_filter.cc
+++ b/lib/ui/painting/mask_filter.cc
@@ -11,26 +11,47 @@
 #include "lib/tonic/converter/dart_converter.h"
 #include "lib/tonic/dart_library_natives.h"
 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/effects/SkShadowMaskFilter.h"
 
 namespace blink {
 
-static void MaskFilter_constructor(Dart_NativeArguments args) {
-  DartCallConstructor(&MaskFilter::Create, args);
+static void MaskFilter_constructorBlur(Dart_NativeArguments args) {
+  DartCallConstructor(&MaskFilter::CreateBlur, args);
+}
+
+static void MaskFilter_constructorShadow(Dart_NativeArguments args) {
+  DartCallConstructor(&MaskFilter::CreateShadow, args);
 }
 
 IMPLEMENT_WRAPPERTYPEINFO(ui, MaskFilter);
 
 void MaskFilter::RegisterNatives(tonic::DartLibraryNatives* natives) {
   natives->Register({
-      {"MaskFilter_constructor", MaskFilter_constructor, 3, true},
+      {"MaskFilter_constructorBlur", MaskFilter_constructorBlur, 3, true},
+      {"MaskFilter_constructorShadow", MaskFilter_constructorShadow, 8, true},
   });
 }
 
-ftl::RefPtr<MaskFilter> MaskFilter::Create(unsigned style, double sigma) {
+ftl::RefPtr<MaskFilter> MaskFilter::CreateBlur(unsigned style, double sigma) {
   return ftl::MakeRefCounted<MaskFilter>(
       SkBlurMaskFilter::Make(static_cast<SkBlurStyle>(style), sigma));
 }
 
+ftl::RefPtr<MaskFilter> MaskFilter::CreateShadow(double occluderHeight,
+                                                 double lightPosX,
+                                                 double lightPosY,
+                                                 double lightPosZ,
+                                                 double lightRadius,
+                                                 double ambientAlpha,
+                                                 double spotAlpha) {
+  return ftl::MakeRefCounted<MaskFilter>(
+      SkShadowMaskFilter::Make(occluderHeight,
+                               SkPoint3::Make(lightPosX, lightPosY, lightPosZ),
+                               lightRadius,
+                               ambientAlpha,
+                               spotAlpha));
+}
+
 MaskFilter::MaskFilter(sk_sp<SkMaskFilter> filter)
     : filter_(std::move(filter)) {}
 
diff --git a/lib/ui/painting/mask_filter.h b/lib/ui/painting/mask_filter.h
index 902be41..4102176 100644
--- a/lib/ui/painting/mask_filter.h
+++ b/lib/ui/painting/mask_filter.h
@@ -23,7 +23,15 @@
 
  public:
   ~MaskFilter() override;
-  static ftl::RefPtr<MaskFilter> Create(unsigned style, double sigma);
+  static ftl::RefPtr<MaskFilter> CreateBlur(unsigned style, double sigma);
+
+  static ftl::RefPtr<MaskFilter> CreateShadow(double occluderHeight,
+                                              double lightPosX,
+                                              double lightPosY,
+                                              double lightPosZ,
+                                              double lightRadius,
+                                              double ambientAlpha,
+                                              double spotAlpha);
 
   const sk_sp<SkMaskFilter>& filter() { return filter_; }