Revert "Remove dlCanvasRecorder from flutter::PictureRecorder (#38127)"

This reverts commit 6aa4ccd60d20ee8f00f91bb526dd5c5546b4f260.
diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc
index 18c5288..733b8a2 100644
--- a/lib/ui/painting/canvas.cc
+++ b/lib/ui/painting/canvas.cc
@@ -56,16 +56,16 @@
   fml::RefPtr<Canvas> canvas = fml::MakeRefCounted<Canvas>(
       recorder->BeginRecording(SkRect::MakeLTRB(left, top, right, bottom)));
   recorder->set_canvas(canvas);
+  canvas->display_list_recorder_ = recorder->display_list_recorder();
   canvas->AssociateWithDartWrapper(wrapper);
 }
 
-Canvas::Canvas(sk_sp<DisplayListBuilder> builder)
-    : display_list_builder_(std::move(builder)) {}
+Canvas::Canvas(SkCanvas* canvas) : canvas_(canvas) {}
 
 Canvas::~Canvas() {}
 
 void Canvas::save() {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->save();
   }
 }
@@ -75,7 +75,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     bool restore_with_paint =
         paint.sync_to(builder(), kSaveLayerWithPaintFlags);
     FML_DCHECK(restore_with_paint);
@@ -94,7 +94,7 @@
 
   FML_DCHECK(paint.isNotNull());
   SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     bool restore_with_paint =
         paint.sync_to(builder(), kSaveLayerWithPaintFlags);
     FML_DCHECK(restore_with_paint);
@@ -104,13 +104,13 @@
 }
 
 void Canvas::restore() {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->restore();
   }
 }
 
 int Canvas::getSaveCount() {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     return builder()->getSaveCount();
   } else {
     return 0;
@@ -118,31 +118,31 @@
 }
 
 void Canvas::restoreToCount(int count) {
-  if (display_list_builder_ && count < getSaveCount()) {
+  if (display_list_recorder_ && count < getSaveCount()) {
     builder()->restoreToCount(count);
   }
 }
 
 void Canvas::translate(double dx, double dy) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->translate(dx, dy);
   }
 }
 
 void Canvas::scale(double sx, double sy) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->scale(sx, sy);
   }
 }
 
 void Canvas::rotate(double radians) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->rotate(radians * 180.0 / M_PI);
   }
 }
 
 void Canvas::skew(double sx, double sy) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->skew(sx, sy);
   }
 }
@@ -150,7 +150,7 @@
 void Canvas::transform(const tonic::Float64List& matrix4) {
   // The Float array stored by Dart Matrix4 is in column-major order
   // Both DisplayList and SkM44 constructor take row-major matrix order
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     // clang-format off
     builder()->transformFullPerspective(
         matrix4[ 0], matrix4[ 4], matrix4[ 8], matrix4[12],
@@ -162,7 +162,10 @@
 }
 
 void Canvas::getTransform(Dart_Handle matrix4_handle) {
-  SkM44 sk_m44 = display_list_builder_->getTransformFullPerspective();
+  SkM44 sk_m44 =
+      display_list_recorder_
+          ? display_list_recorder_->builder()->getTransformFullPerspective()
+          : canvas_->getLocalToDevice();
   SkScalar m44_values[16];
   // The Float array stored by Dart Matrix4 is in column-major order
   sk_m44.getColMajor(m44_values);
@@ -178,14 +181,14 @@
                       double bottom,
                       SkClipOp clipOp,
                       bool doAntiAlias) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->clipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
                         doAntiAlias);
   }
 }
 
 void Canvas::clipRRect(const RRect& rrect, bool doAntiAlias) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->clipRRect(rrect.sk_rrect, SkClipOp::kIntersect, doAntiAlias);
   }
 }
@@ -196,13 +199,13 @@
         ToDart("Canvas.clipPath called with non-genuine Path."));
     return;
   }
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->clipPath(path->path(), SkClipOp::kIntersect, doAntiAlias);
   }
 }
 
 void Canvas::getDestinationClipBounds(Dart_Handle rect_handle) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     auto rect = tonic::Float64List(rect_handle);
     SkRect bounds = builder()->getDestinationClipBounds();
     rect[0] = bounds.fLeft;
@@ -213,9 +216,9 @@
 }
 
 void Canvas::getLocalClipBounds(Dart_Handle rect_handle) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     auto rect = tonic::Float64List(rect_handle);
-    SkRect bounds = display_list_builder_->getLocalClipBounds();
+    SkRect bounds = display_list_recorder_->builder()->getLocalClipBounds();
     rect[0] = bounds.fLeft;
     rect[1] = bounds.fTop;
     rect[2] = bounds.fRight;
@@ -224,7 +227,7 @@
 }
 
 void Canvas::drawColor(SkColor color, DlBlendMode blend_mode) {
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     builder()->drawColor(color, blend_mode);
   }
 }
@@ -238,7 +241,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawLineFlags);
     builder()->drawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
   }
@@ -248,7 +251,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawPaintFlags);
     std::shared_ptr<const DlImageFilter> filter = builder()->getImageFilter();
     if (filter && !filter->asColorFilter()) {
@@ -269,7 +272,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawRectFlags);
     builder()->drawRect(SkRect::MakeLTRB(left, top, right, bottom));
   }
@@ -281,7 +284,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawRRectFlags);
     builder()->drawRRect(rrect.sk_rrect);
   }
@@ -294,7 +297,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawDRRectFlags);
     builder()->drawDRRect(outer.sk_rrect, inner.sk_rrect);
   }
@@ -309,7 +312,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawOvalFlags);
     builder()->drawOval(SkRect::MakeLTRB(left, top, right, bottom));
   }
@@ -323,7 +326,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawCircleFlags);
     builder()->drawCircle(SkPoint::Make(x, y), radius);
   }
@@ -341,7 +344,7 @@
   Paint paint(paint_objects, paint_data);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(),
                   useCenter  //
                       ? kDrawArcWithCenterFlags
@@ -363,7 +366,7 @@
         ToDart("Canvas.drawPath called with non-genuine Path."));
     return;
   }
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawPathFlags);
     builder()->drawPath(path->path());
   }
@@ -392,7 +395,7 @@
   }
 
   auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     bool with_attributes = paint.sync_to(builder(), kDrawImageWithPaintFlags);
     builder()->drawImage(dl_image, SkPoint::Make(x, y), sampling,
                          with_attributes);
@@ -431,7 +434,7 @@
   SkRect src = SkRect::MakeLTRB(src_left, src_top, src_right, src_bottom);
   SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
   auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     bool with_attributes =
         paint.sync_to(builder(), kDrawImageRectWithPaintFlags);
     builder()->drawImageRect(dl_image, src, dst, sampling, with_attributes,
@@ -473,7 +476,7 @@
   center.round(&icenter);
   SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
   auto filter = ImageFilter::FilterModeFromIndex(bitmapSamplingIndex);
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     bool with_attributes =
         paint.sync_to(builder(), kDrawImageNineWithPaintFlags);
     builder()->drawImageNine(dl_image, icenter, dst, filter, with_attributes);
@@ -488,8 +491,10 @@
     return;
   }
   if (picture->display_list()) {
-    if (display_list_builder_) {
+    if (display_list_recorder_) {
       builder()->drawDisplayList(picture->display_list());
+    } else if (canvas_) {
+      picture->display_list()->RenderTo(canvas_);
     }
   } else {
     FML_DCHECK(false);
@@ -506,7 +511,7 @@
                 "SkPoint doesn't use floats.");
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     switch (point_mode) {
       case SkCanvas::kPoints_PointMode:
         paint.sync_to(builder(), kDrawPointsAsPointsFlags);
@@ -536,7 +541,7 @@
     return;
   }
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     paint.sync_to(builder(), kDrawVerticesFlags);
     builder()->drawVertices(vertices->vertices(), blend_mode);
   }
@@ -573,7 +578,7 @@
   auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
 
   FML_DCHECK(paint.isNotNull());
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     tonic::Float32List transforms(transforms_handle);
     tonic::Float32List rects(rects_handle);
     tonic::Int32List colors(colors_handle);
@@ -605,7 +610,7 @@
                      ->get_window(0)
                      ->viewport_metrics()
                      .device_pixel_ratio;
-  if (display_list_builder_) {
+  if (display_list_recorder_) {
     // The DrawShadow mechanism results in non-public operations to be
     // performed on the canvas involving an SkDrawShadowRec. Since we
     // cannot include the header that defines that structure, we cannot
@@ -619,7 +624,8 @@
 }
 
 void Canvas::Invalidate() {
-  display_list_builder_ = nullptr;
+  canvas_ = nullptr;
+  display_list_recorder_ = nullptr;
   if (dart_wrapper()) {
     ClearDartWrapper();
   }
diff --git a/lib/ui/painting/canvas.h b/lib/ui/painting/canvas.h
index bf793ae..0855c52 100644
--- a/lib/ui/painting/canvas.h
+++ b/lib/ui/painting/canvas.h
@@ -14,6 +14,8 @@
 #include "flutter/lib/ui/painting/rrect.h"
 #include "flutter/lib/ui/painting/vertices.h"
 #include "flutter/lib/ui/ui_dart_state.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/utils/SkShadowUtils.h"
 #include "third_party/tonic/typed_data/typed_list.h"
 
 namespace flutter {
@@ -185,12 +187,21 @@
                   double elevation,
                   bool transparentOccluder);
 
+  SkCanvas* canvas() const { return canvas_; }
   void Invalidate();
 
-  DisplayListBuilder* builder() { return display_list_builder_.get(); }
+  DisplayListBuilder* builder() {
+    return display_list_recorder_ ? display_list_recorder_->builder().get()
+                                  : nullptr;
+  }
 
  private:
-  explicit Canvas(sk_sp<DisplayListBuilder> canvas);
+  explicit Canvas(SkCanvas* canvas);
+
+  // The SkCanvas is supplied by a call to SkPictureRecorder::beginRecording,
+  // which does not transfer ownership.  For this reason, we hold a raw
+  // pointer and manually set to null in Clear.
+  SkCanvas* canvas_;
 
   // A copy of the recorder used by the SkCanvas->DisplayList adapter for cases
   // where we cannot record the SkCanvas method call through the various OnOp()
@@ -198,7 +209,7 @@
   // the DisplayList operation lexicon. The recorder has a method for recording
   // paint attributes from an SkPaint and an operation type as well as access
   // to the raw DisplayListBuilder for emitting custom rendering operations.
-  sk_sp<DisplayListBuilder> display_list_builder_;
+  sk_sp<DisplayListCanvasRecorder> display_list_recorder_;
 };
 
 }  // namespace flutter
diff --git a/lib/ui/painting/picture.h b/lib/ui/painting/picture.h
index fbe800c..33bee19 100644
--- a/lib/ui/painting/picture.h
+++ b/lib/ui/painting/picture.h
@@ -11,6 +11,7 @@
 #include "flutter/lib/ui/dart_wrapper.h"
 #include "flutter/lib/ui/painting/image.h"
 #include "flutter/lib/ui/ui_dart_state.h"
+#include "third_party/skia/include/core/SkPicture.h"
 
 namespace flutter {
 class Canvas;
diff --git a/lib/ui/painting/picture_recorder.cc b/lib/ui/painting/picture_recorder.cc
index 97e101a..8a62560 100644
--- a/lib/ui/painting/picture_recorder.cc
+++ b/lib/ui/painting/picture_recorder.cc
@@ -26,9 +26,9 @@
 
 PictureRecorder::~PictureRecorder() {}
 
-sk_sp<DisplayListBuilder> PictureRecorder::BeginRecording(SkRect bounds) {
-  display_list_builder_ = sk_make_sp<DisplayListBuilder>(bounds);
-  return display_list_builder_;
+SkCanvas* PictureRecorder::BeginRecording(SkRect bounds) {
+  display_list_recorder_ = sk_make_sp<DisplayListCanvasRecorder>(bounds);
+  return display_list_recorder_.get();
 }
 
 fml::RefPtr<Picture> PictureRecorder::endRecording(Dart_Handle dart_picture) {
@@ -39,8 +39,8 @@
   fml::RefPtr<Picture> picture;
 
   picture = Picture::Create(dart_picture, UIDartState::CreateGPUObject(
-                                              display_list_builder_->Build()));
-  display_list_builder_ = nullptr;
+                                              display_list_recorder_->Build()));
+  display_list_recorder_ = nullptr;
 
   canvas_->Invalidate();
   canvas_ = nullptr;
diff --git a/lib/ui/painting/picture_recorder.h b/lib/ui/painting/picture_recorder.h
index 1fc9dbe..f510da7 100644
--- a/lib/ui/painting/picture_recorder.h
+++ b/lib/ui/painting/picture_recorder.h
@@ -5,8 +5,9 @@
 #ifndef FLUTTER_LIB_UI_PAINTING_PICTURE_RECORDER_H_
 #define FLUTTER_LIB_UI_PAINTING_PICTURE_RECORDER_H_
 
-#include "flutter/display_list/display_list_builder.h"
+#include "flutter/display_list/display_list_canvas_recorder.h"
 #include "flutter/lib/ui/dart_wrapper.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
 
 namespace flutter {
 class Canvas;
@@ -21,11 +22,11 @@
 
   ~PictureRecorder() override;
 
-  sk_sp<DisplayListBuilder> BeginRecording(SkRect bounds);
+  SkCanvas* BeginRecording(SkRect bounds);
   fml::RefPtr<Picture> endRecording(Dart_Handle dart_picture);
 
-  sk_sp<DisplayListBuilder> display_list_builder() {
-    return display_list_builder_;
+  sk_sp<DisplayListCanvasRecorder> display_list_recorder() {
+    return display_list_recorder_;
   }
 
   void set_canvas(fml::RefPtr<Canvas> canvas) { canvas_ = std::move(canvas); }
@@ -33,7 +34,7 @@
  private:
   PictureRecorder();
 
-  sk_sp<DisplayListBuilder> display_list_builder_;
+  sk_sp<DisplayListCanvasRecorder> display_list_recorder_;
 
   fml::RefPtr<Canvas> canvas_;
 };
diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc
index 624ed14..4b3df64 100644
--- a/lib/ui/text/paragraph.cc
+++ b/lib/ui/text/paragraph.cc
@@ -65,8 +65,13 @@
   }
 
   DisplayListBuilder* builder = canvas->builder();
-  if (builder) {
-    m_paragraph->Paint(builder, x, y);
+  if (builder && m_paragraph->Paint(builder, x, y)) {
+    return;
+  }
+  // Fall back to SkCanvas if painting to DisplayListBuilder is not supported.
+  SkCanvas* sk_canvas = canvas->canvas();
+  if (sk_canvas) {
+    m_paragraph->Paint(sk_canvas, x, y);
   }
 }