Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 48 additions & 71 deletions lib/ui/painting/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,16 @@
// found in the LICENSE file.

#include "flutter/lib/ui/painting/canvas.h"
#include "flutter/lib/ui/painting/image_filter.h"

#include <cmath>

#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/flow/layers/physical_shape_layer.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/matrix.h"
#include "flutter/lib/ui/painting/image_filter.h"
#include "flutter/lib/ui/painting/paint.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/platform_configuration.h"
#include "flutter/lib/ui/window/window.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkRSXform.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"

using tonic::ToDart;

Expand All @@ -45,27 +34,19 @@ void Canvas::Create(Dart_Handle wrapper,
return;
}

// This call will implicitly initialize the |canvas_| field with an SkCanvas
// whether or not we are using display_list. Now that all of the code here
// in canvas.cc will direct calls to the DisplayListBuilder we could almost
// stop initializing that field for the display list case. Unfortunately,
// the text code in paragraph.cc still needs to present its output to an
// SkCanvas* which means without significant work to the internals of the
// paragraph code, we are going to continue to need the canvas adapter and
// field and getter.
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(SkCanvas* canvas) : canvas_(canvas) {}
Canvas::Canvas(sk_sp<DisplayListBuilder> builder)
: display_list_builder_(std::move(builder)) {}

Canvas::~Canvas() {}

void Canvas::save() {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->save();
}
}
Expand All @@ -75,7 +56,7 @@ void Canvas::saveLayerWithoutBounds(Dart_Handle paint_objects,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
bool restore_with_paint =
paint.sync_to(builder(), kSaveLayerWithPaintFlags);
FML_DCHECK(restore_with_paint);
Expand All @@ -94,7 +75,7 @@ void Canvas::saveLayer(double left,

FML_DCHECK(paint.isNotNull());
SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
if (display_list_recorder_) {
if (display_list_builder_) {
bool restore_with_paint =
paint.sync_to(builder(), kSaveLayerWithPaintFlags);
FML_DCHECK(restore_with_paint);
Expand All @@ -104,53 +85,53 @@ void Canvas::saveLayer(double left,
}

void Canvas::restore() {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->restore();
}
}

int Canvas::getSaveCount() {
if (display_list_recorder_) {
if (display_list_builder_) {
return builder()->getSaveCount();
} else {
return 0;
}
}

void Canvas::restoreToCount(int count) {
if (display_list_recorder_ && count < getSaveCount()) {
if (display_list_builder_ && count < getSaveCount()) {
builder()->restoreToCount(count);
}
}

void Canvas::translate(double dx, double dy) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->translate(dx, dy);
}
}

void Canvas::scale(double sx, double sy) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->scale(sx, sy);
}
}

void Canvas::rotate(double radians) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->rotate(radians * 180.0 / M_PI);
}
}

void Canvas::skew(double sx, double sy) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->skew(sx, 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_recorder_) {
if (display_list_builder_) {
// clang-format off
builder()->transformFullPerspective(
matrix4[ 0], matrix4[ 4], matrix4[ 8], matrix4[12],
Expand All @@ -162,16 +143,15 @@ void Canvas::transform(const tonic::Float64List& matrix4) {
}

void Canvas::getTransform(Dart_Handle matrix4_handle) {
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);
auto matrix4 = tonic::Float64List(matrix4_handle);
for (int i = 0; i < 16; i++) {
matrix4[i] = m44_values[i];
if (display_list_builder_) {
SkM44 sk_m44 = builder()->getTransformFullPerspective();
SkScalar m44_values[16];
// The Float array stored by Dart Matrix4 is in column-major order
sk_m44.getColMajor(m44_values);
auto matrix4 = tonic::Float64List(matrix4_handle);
for (int i = 0; i < 16; i++) {
matrix4[i] = m44_values[i];
}
}
}

Expand All @@ -181,14 +161,14 @@ void Canvas::clipRect(double left,
double bottom,
SkClipOp clipOp,
bool doAntiAlias) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->clipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
doAntiAlias);
}
}

void Canvas::clipRRect(const RRect& rrect, bool doAntiAlias) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->clipRRect(rrect.sk_rrect, SkClipOp::kIntersect, doAntiAlias);
}
}
Expand All @@ -199,13 +179,13 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) {
ToDart("Canvas.clipPath called with non-genuine Path."));
return;
}
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->clipPath(path->path(), SkClipOp::kIntersect, doAntiAlias);
}
}

void Canvas::getDestinationClipBounds(Dart_Handle rect_handle) {
if (display_list_recorder_) {
if (display_list_builder_) {
auto rect = tonic::Float64List(rect_handle);
SkRect bounds = builder()->getDestinationClipBounds();
rect[0] = bounds.fLeft;
Expand All @@ -216,9 +196,9 @@ void Canvas::getDestinationClipBounds(Dart_Handle rect_handle) {
}

void Canvas::getLocalClipBounds(Dart_Handle rect_handle) {
if (display_list_recorder_) {
if (display_list_builder_) {
auto rect = tonic::Float64List(rect_handle);
SkRect bounds = display_list_recorder_->builder()->getLocalClipBounds();
SkRect bounds = builder()->getLocalClipBounds();
rect[0] = bounds.fLeft;
rect[1] = bounds.fTop;
rect[2] = bounds.fRight;
Expand All @@ -227,7 +207,7 @@ void Canvas::getLocalClipBounds(Dart_Handle rect_handle) {
}

void Canvas::drawColor(SkColor color, DlBlendMode blend_mode) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->drawColor(color, blend_mode);
}
}
Expand All @@ -241,7 +221,7 @@ void Canvas::drawLine(double x1,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawLineFlags);
builder()->drawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
}
Expand All @@ -251,7 +231,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_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawPaintFlags);
std::shared_ptr<const DlImageFilter> filter = builder()->getImageFilter();
if (filter && !filter->asColorFilter()) {
Expand All @@ -272,7 +252,7 @@ void Canvas::drawRect(double left,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawRectFlags);
builder()->drawRect(SkRect::MakeLTRB(left, top, right, bottom));
}
Expand All @@ -284,7 +264,7 @@ void Canvas::drawRRect(const RRect& rrect,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawRRectFlags);
builder()->drawRRect(rrect.sk_rrect);
}
Expand All @@ -297,7 +277,7 @@ void Canvas::drawDRRect(const RRect& outer,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawDRRectFlags);
builder()->drawDRRect(outer.sk_rrect, inner.sk_rrect);
}
Expand All @@ -312,7 +292,7 @@ void Canvas::drawOval(double left,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawOvalFlags);
builder()->drawOval(SkRect::MakeLTRB(left, top, right, bottom));
}
Expand All @@ -326,7 +306,7 @@ void Canvas::drawCircle(double x,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawCircleFlags);
builder()->drawCircle(SkPoint::Make(x, y), radius);
}
Expand All @@ -344,7 +324,7 @@ void Canvas::drawArc(double left,
Paint paint(paint_objects, paint_data);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(),
useCenter //
? kDrawArcWithCenterFlags
Expand All @@ -366,7 +346,7 @@ void Canvas::drawPath(const CanvasPath* path,
ToDart("Canvas.drawPath called with non-genuine Path."));
return;
}
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawPathFlags);
builder()->drawPath(path->path());
}
Expand Down Expand Up @@ -395,7 +375,7 @@ Dart_Handle Canvas::drawImage(const CanvasImage* image,
}

auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
if (display_list_recorder_) {
if (display_list_builder_) {
bool with_attributes = paint.sync_to(builder(), kDrawImageWithPaintFlags);
builder()->drawImage(dl_image, SkPoint::Make(x, y), sampling,
with_attributes);
Expand Down Expand Up @@ -434,7 +414,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_recorder_) {
if (display_list_builder_) {
bool with_attributes =
paint.sync_to(builder(), kDrawImageRectWithPaintFlags);
builder()->drawImageRect(dl_image, src, dst, sampling, with_attributes,
Expand Down Expand Up @@ -476,7 +456,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_recorder_) {
if (display_list_builder_) {
bool with_attributes =
paint.sync_to(builder(), kDrawImageNineWithPaintFlags);
builder()->drawImageNine(dl_image, icenter, dst, filter, with_attributes);
Expand All @@ -491,10 +471,8 @@ void Canvas::drawPicture(Picture* picture) {
return;
}
if (picture->display_list()) {
if (display_list_recorder_) {
if (display_list_builder_) {
builder()->drawDisplayList(picture->display_list());
} else if (canvas_) {
picture->display_list()->RenderTo(canvas_);
}
} else {
FML_DCHECK(false);
Expand All @@ -511,7 +489,7 @@ void Canvas::drawPoints(Dart_Handle paint_objects,
"SkPoint doesn't use floats.");

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
switch (point_mode) {
case SkCanvas::kPoints_PointMode:
paint.sync_to(builder(), kDrawPointsAsPointsFlags);
Expand Down Expand Up @@ -541,7 +519,7 @@ void Canvas::drawVertices(const Vertices* vertices,
return;
}
FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
paint.sync_to(builder(), kDrawVerticesFlags);
builder()->drawVertices(vertices->vertices(), blend_mode);
}
Expand Down Expand Up @@ -578,7 +556,7 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects,
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);

FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
if (display_list_builder_) {
tonic::Float32List transforms(transforms_handle);
tonic::Float32List rects(rects_handle);
tonic::Int32List colors(colors_handle);
Expand Down Expand Up @@ -610,7 +588,7 @@ void Canvas::drawShadow(const CanvasPath* path,
->get_window(0)
->viewport_metrics()
.device_pixel_ratio;
if (display_list_recorder_) {
if (display_list_builder_) {
// 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
Expand All @@ -624,8 +602,7 @@ void Canvas::drawShadow(const CanvasPath* path,
}

void Canvas::Invalidate() {
canvas_ = nullptr;
display_list_recorder_ = nullptr;
display_list_builder_ = nullptr;
if (dart_wrapper()) {
ClearDartWrapper();
}
Expand Down
Loading