diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index 18c52880a4146..733b8a2903e71 100644 --- a/lib/ui/painting/canvas.cc +++ b/lib/ui/painting/canvas.cc @@ -56,16 +56,16 @@ void Canvas::Create(Dart_Handle wrapper, fml::RefPtr canvas = fml::MakeRefCounted( 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 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 @@ void Canvas::saveLayerWithoutBounds(Dart_Handle paint_objects, 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 @@ void Canvas::saveLayer(double left, 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::saveLayer(double left, } 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 @@ int Canvas::getSaveCount() { } 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::skew(double sx, double sy) { 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::transform(const tonic::Float64List& matrix4) { } 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 @@ void Canvas::clipRect(double left, 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 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) { 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::getDestinationClipBounds(Dart_Handle rect_handle) { } 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::getLocalClipBounds(Dart_Handle rect_handle) { } 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 @@ void Canvas::drawLine(double x1, 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 @@ void Canvas::drawPaint(Dart_Handle paint_objects, Dart_Handle paint_data) { 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 filter = builder()->getImageFilter(); if (filter && !filter->asColorFilter()) { @@ -269,7 +272,7 @@ void Canvas::drawRect(double left, 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 @@ void Canvas::drawRRect(const RRect& rrect, 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 @@ void Canvas::drawDRRect(const RRect& outer, 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 @@ void Canvas::drawOval(double left, 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 @@ void Canvas::drawCircle(double x, 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 @@ void Canvas::drawArc(double left, 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 @@ void Canvas::drawPath(const CanvasPath* path, 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 @@ Dart_Handle Canvas::drawImage(const CanvasImage* image, } 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 @@ Dart_Handle Canvas::drawImageRect(const CanvasImage* image, 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 @@ Dart_Handle Canvas::drawImageNine(const CanvasImage* image, 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 @@ void Canvas::drawPicture(Picture* picture) { 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 @@ void Canvas::drawPoints(Dart_Handle paint_objects, "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 @@ void Canvas::drawVertices(const Vertices* vertices, 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 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects, 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 @@ void Canvas::drawShadow(const CanvasPath* path, ->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::drawShadow(const CanvasPath* path, } 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 bf793ae821969..0855c52c20f8c 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 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { 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 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 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { // 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 display_list_builder_; + sk_sp display_list_recorder_; }; } // namespace flutter diff --git a/lib/ui/painting/picture.h b/lib/ui/painting/picture.h index fbe800c51172e..33bee1994f9ec 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 97e101a5f4dc0..8a625603d3a1c 100644 --- a/lib/ui/painting/picture_recorder.cc +++ b/lib/ui/painting/picture_recorder.cc @@ -26,9 +26,9 @@ PictureRecorder::PictureRecorder() {} PictureRecorder::~PictureRecorder() {} -sk_sp PictureRecorder::BeginRecording(SkRect bounds) { - display_list_builder_ = sk_make_sp(bounds); - return display_list_builder_; +SkCanvas* PictureRecorder::BeginRecording(SkRect bounds) { + display_list_recorder_ = sk_make_sp(bounds); + return display_list_recorder_.get(); } fml::RefPtr PictureRecorder::endRecording(Dart_Handle dart_picture) { @@ -39,8 +39,8 @@ fml::RefPtr PictureRecorder::endRecording(Dart_Handle dart_picture) { fml::RefPtr 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 1fc9dbe882537..f510da77a1999 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 @@ class PictureRecorder : public RefCountedDartWrappable { ~PictureRecorder() override; - sk_sp BeginRecording(SkRect bounds); + SkCanvas* BeginRecording(SkRect bounds); fml::RefPtr endRecording(Dart_Handle dart_picture); - sk_sp display_list_builder() { - return display_list_builder_; + sk_sp display_list_recorder() { + return display_list_recorder_; } void set_canvas(fml::RefPtr canvas) { canvas_ = std::move(canvas); } @@ -33,7 +34,7 @@ class PictureRecorder : public RefCountedDartWrappable { private: PictureRecorder(); - sk_sp display_list_builder_; + sk_sp display_list_recorder_; fml::RefPtr canvas_; }; diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index 624ed145dcf38..4b3df6439186d 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -65,8 +65,13 @@ void Paragraph::paint(Canvas* canvas, double x, double y) { } 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); } }