Skip to content

Commit

Permalink
add currentTransform/Clip methods to DL and ui.Canvas (flutter#33308)
Browse files Browse the repository at this point in the history
  • Loading branch information
flar authored Jun 15, 2022
1 parent 68f11fa commit 45de099
Show file tree
Hide file tree
Showing 22 changed files with 1,341 additions and 64 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ vars = {

# WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY
# See `lib/web_ui/README.md` for how to roll CanvasKit to a new version.
'canvaskit_cipd_instance': '8MSYGWVWzrTJIoVL00ZquruZs-weuwLBy1kt1AawJiIC',
'canvaskit_cipd_instance': '4PosNKiHa3EaBK4alMD4idrKYxAk0I0QiRVDDQplhOYC',

# Do not download the Emscripten SDK by default.
# This prevents us from downloading the Emscripten toolchain for builds
Expand Down
70 changes: 58 additions & 12 deletions display_list/display_list_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ sk_sp<DisplayList> DisplayListBuilder::Build() {

DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect)
: cull_rect_(cull_rect) {
layer_stack_.emplace_back();
layer_stack_.emplace_back(SkM44(), cull_rect);
current_layer_ = &layer_stack_.back();
}

Expand Down Expand Up @@ -415,7 +415,7 @@ void DisplayListBuilder::setAttributesFromPaint(

void DisplayListBuilder::save() {
Push<SaveOp>(0, 1);
layer_stack_.emplace_back();
layer_stack_.emplace_back(current_layer_);
current_layer_ = &layer_stack_.back();
}
void DisplayListBuilder::restore() {
Expand Down Expand Up @@ -476,7 +476,7 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
: Push<SaveLayerOp>(0, 1, options);
}
CheckLayerOpacityCompatibility(options.renders_with_attributes());
layer_stack_.emplace_back(save_layer_offset, true);
layer_stack_.emplace_back(current_layer_, save_layer_offset, true);
current_layer_ = &layer_stack_.back();
if (options.renders_with_attributes()) {
// |current_opacity_compatibility_| does not take an ImageFilter into
Expand Down Expand Up @@ -505,23 +505,27 @@ void DisplayListBuilder::translate(SkScalar tx, SkScalar ty) {
if (SkScalarIsFinite(tx) && SkScalarIsFinite(ty) &&
(tx != 0.0 || ty != 0.0)) {
Push<TranslateOp>(0, 1, tx, ty);
current_layer_->matrix.preTranslate(tx, ty);
}
}
void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) {
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
(sx != 1.0 || sy != 1.0)) {
Push<ScaleOp>(0, 1, sx, sy);
current_layer_->matrix.preScale(sx, sy);
}
}
void DisplayListBuilder::rotate(SkScalar degrees) {
if (SkScalarMod(degrees, 360.0) != 0.0) {
Push<RotateOp>(0, 1, degrees);
current_layer_->matrix.preConcat(SkMatrix::RotateDeg(degrees));
}
}
void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) {
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
(sx != 0.0 || sy != 0.0)) {
Push<SkewOp>(0, 1, sx, sy);
current_layer_->matrix.preConcat(SkMatrix::Skew(sx, sy));
}
}

Expand All @@ -539,6 +543,10 @@ void DisplayListBuilder::transform2DAffine(
Push<Transform2DAffineOp>(0, 1,
mxx, mxy, mxt,
myx, myy, myt);
current_layer_->matrix.preConcat(SkM44(mxx, mxy, 0, mxt,
myx, myy, 0, myt,
0, 0, 1, 0,
0, 0, 0, 1));
}
}
// full 4x4 transform in row major order
Expand All @@ -562,11 +570,16 @@ void DisplayListBuilder::transformFullPerspective(
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt);
current_layer_->matrix.preConcat(SkM44(mxx, mxy, mxz, mxt,
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt));
}
}
// clang-format on
void DisplayListBuilder::transformReset() {
Push<TransformResetOp>(0, 0);
current_layer_->matrix.setIdentity();
}
void DisplayListBuilder::transform(const SkMatrix* matrix) {
if (matrix != nullptr) {
Expand All @@ -586,19 +599,35 @@ void DisplayListBuilder::transform(const SkM44* m44) {
void DisplayListBuilder::clipRect(const SkRect& rect,
SkClipOp clip_op,
bool is_aa) {
clip_op == SkClipOp::kIntersect //
? Push<ClipIntersectRectOp>(0, 1, rect, is_aa)
: Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectRectOp>(0, 1, rect, is_aa);
if (!current_layer_->clip_bounds.intersect(rect)) {
current_layer_->clip_bounds.setEmpty();
}
break;
case SkClipOp::kDifference:
Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
break;
}
}
void DisplayListBuilder::clipRRect(const SkRRect& rrect,
SkClipOp clip_op,
bool is_aa) {
if (rrect.isRect()) {
clipRect(rrect.rect(), clip_op, is_aa);
} else {
clip_op == SkClipOp::kIntersect //
? Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa)
: Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa);
if (!current_layer_->clip_bounds.intersect(rrect.getBounds())) {
current_layer_->clip_bounds.setEmpty();
}
break;
case SkClipOp::kDifference:
Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
break;
}
}
}
void DisplayListBuilder::clipPath(const SkPath& path,
Expand All @@ -621,9 +650,26 @@ void DisplayListBuilder::clipPath(const SkPath& path,
return;
}
}
clip_op == SkClipOp::kIntersect //
? Push<ClipIntersectPathOp>(0, 1, path, is_aa)
: Push<ClipDifferencePathOp>(0, 1, path, is_aa);
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectPathOp>(0, 1, path, is_aa);
if (!current_layer_->clip_bounds.intersect(path.getBounds())) {
current_layer_->clip_bounds.setEmpty();
}
break;
case SkClipOp::kDifference:
Push<ClipDifferencePathOp>(0, 1, path, is_aa);
break;
}
}
SkRect DisplayListBuilder::getLocalClipBounds() {
SkM44 inverse;
if (current_layer_->matrix.invert(&inverse)) {
SkRect devBounds;
current_layer_->clip_bounds.roundOut(&devBounds);
return inverse.asM33().mapRect(devBounds);
}
return kMaxCullRect_;
}

void DisplayListBuilder::drawPaint() {
Expand Down
38 changes: 36 additions & 2 deletions display_list/display_list_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,28 @@ class DisplayListBuilder final : public virtual Dispatcher,
void transform(const SkMatrix& matrix) { transform(&matrix); }
void transform(const SkM44& matrix44) { transform(&matrix44); }

/// Returns the 4x4 full perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkM44 getTransformFullPerspective() { return current_layer_->matrix; }
/// Returns the 3x3 partial perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkMatrix getTransform() { return current_layer_->matrix.asM33(); }

void clipRect(const SkRect& rect, SkClipOp clip_op, bool is_aa) override;
void clipRRect(const SkRRect& rrect, SkClipOp clip_op, bool is_aa) override;
void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override;

/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will
/// be rendered.
SkRect getDestinationClipBounds() { return current_layer_->clip_bounds; }
/// Conservative estimate of the bounds of all outstanding clip operations
/// transformed into the local coordinate space in which currently
/// recorded rendering operations are interpreted.
SkRect getLocalClipBounds();

void drawPaint() override;
void drawPaint(const DlPaint& paint);
void drawColor(DlColor color, DlBlendMode mode) override;
Expand Down Expand Up @@ -350,11 +368,24 @@ class DisplayListBuilder final : public virtual Dispatcher,
}

struct LayerInfo {
LayerInfo(size_t save_layer_offset = 0, bool has_layer = false)
LayerInfo(const SkM44& matrix,
const SkRect& clip_bounds,
size_t save_layer_offset = 0,
bool has_layer = false)
: save_layer_offset(save_layer_offset),
has_layer(has_layer),
cannot_inherit_opacity(false),
has_compatible_op(false) {}
has_compatible_op(false),
matrix(matrix),
clip_bounds(clip_bounds) {}

LayerInfo(const LayerInfo* current_layer,
size_t save_layer_offset = 0,
bool has_layer = false)
: LayerInfo(current_layer->matrix,
current_layer->clip_bounds,
save_layer_offset,
has_layer) {}

// The offset into the memory buffer where the saveLayer DLOp record
// for this saveLayer() call is placed. This may be needed if the
Expand All @@ -368,6 +399,9 @@ class DisplayListBuilder final : public virtual Dispatcher,
bool cannot_inherit_opacity;
bool has_compatible_op;

SkM44 matrix;
SkRect clip_bounds;

bool is_group_opacity_compatible() const { return !cannot_inherit_opacity; }

void mark_incompatible() { cannot_inherit_opacity = true; }
Expand Down
Loading

0 comments on commit 45de099

Please sign in to comment.