Skip to content

Commit 45de099

Browse files
authored
add currentTransform/Clip methods to DL and ui.Canvas (flutter#33308)
1 parent 68f11fa commit 45de099

22 files changed

+1341
-64
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ vars = {
3131

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

3636
# Do not download the Emscripten SDK by default.
3737
# This prevents us from downloading the Emscripten toolchain for builds

display_list/display_list_builder.cc

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ sk_sp<DisplayList> DisplayListBuilder::Build() {
6565

6666
DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect)
6767
: cull_rect_(cull_rect) {
68-
layer_stack_.emplace_back();
68+
layer_stack_.emplace_back(SkM44(), cull_rect);
6969
current_layer_ = &layer_stack_.back();
7070
}
7171

@@ -415,7 +415,7 @@ void DisplayListBuilder::setAttributesFromPaint(
415415

416416
void DisplayListBuilder::save() {
417417
Push<SaveOp>(0, 1);
418-
layer_stack_.emplace_back();
418+
layer_stack_.emplace_back(current_layer_);
419419
current_layer_ = &layer_stack_.back();
420420
}
421421
void DisplayListBuilder::restore() {
@@ -476,7 +476,7 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
476476
: Push<SaveLayerOp>(0, 1, options);
477477
}
478478
CheckLayerOpacityCompatibility(options.renders_with_attributes());
479-
layer_stack_.emplace_back(save_layer_offset, true);
479+
layer_stack_.emplace_back(current_layer_, save_layer_offset, true);
480480
current_layer_ = &layer_stack_.back();
481481
if (options.renders_with_attributes()) {
482482
// |current_opacity_compatibility_| does not take an ImageFilter into
@@ -505,23 +505,27 @@ void DisplayListBuilder::translate(SkScalar tx, SkScalar ty) {
505505
if (SkScalarIsFinite(tx) && SkScalarIsFinite(ty) &&
506506
(tx != 0.0 || ty != 0.0)) {
507507
Push<TranslateOp>(0, 1, tx, ty);
508+
current_layer_->matrix.preTranslate(tx, ty);
508509
}
509510
}
510511
void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) {
511512
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
512513
(sx != 1.0 || sy != 1.0)) {
513514
Push<ScaleOp>(0, 1, sx, sy);
515+
current_layer_->matrix.preScale(sx, sy);
514516
}
515517
}
516518
void DisplayListBuilder::rotate(SkScalar degrees) {
517519
if (SkScalarMod(degrees, 360.0) != 0.0) {
518520
Push<RotateOp>(0, 1, degrees);
521+
current_layer_->matrix.preConcat(SkMatrix::RotateDeg(degrees));
519522
}
520523
}
521524
void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) {
522525
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
523526
(sx != 0.0 || sy != 0.0)) {
524527
Push<SkewOp>(0, 1, sx, sy);
528+
current_layer_->matrix.preConcat(SkMatrix::Skew(sx, sy));
525529
}
526530
}
527531

@@ -539,6 +543,10 @@ void DisplayListBuilder::transform2DAffine(
539543
Push<Transform2DAffineOp>(0, 1,
540544
mxx, mxy, mxt,
541545
myx, myy, myt);
546+
current_layer_->matrix.preConcat(SkM44(mxx, mxy, 0, mxt,
547+
myx, myy, 0, myt,
548+
0, 0, 1, 0,
549+
0, 0, 0, 1));
542550
}
543551
}
544552
// full 4x4 transform in row major order
@@ -562,11 +570,16 @@ void DisplayListBuilder::transformFullPerspective(
562570
myx, myy, myz, myt,
563571
mzx, mzy, mzz, mzt,
564572
mwx, mwy, mwz, mwt);
573+
current_layer_->matrix.preConcat(SkM44(mxx, mxy, mxz, mxt,
574+
myx, myy, myz, myt,
575+
mzx, mzy, mzz, mzt,
576+
mwx, mwy, mwz, mwt));
565577
}
566578
}
567579
// clang-format on
568580
void DisplayListBuilder::transformReset() {
569581
Push<TransformResetOp>(0, 0);
582+
current_layer_->matrix.setIdentity();
570583
}
571584
void DisplayListBuilder::transform(const SkMatrix* matrix) {
572585
if (matrix != nullptr) {
@@ -586,19 +599,35 @@ void DisplayListBuilder::transform(const SkM44* m44) {
586599
void DisplayListBuilder::clipRect(const SkRect& rect,
587600
SkClipOp clip_op,
588601
bool is_aa) {
589-
clip_op == SkClipOp::kIntersect //
590-
? Push<ClipIntersectRectOp>(0, 1, rect, is_aa)
591-
: Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
602+
switch (clip_op) {
603+
case SkClipOp::kIntersect:
604+
Push<ClipIntersectRectOp>(0, 1, rect, is_aa);
605+
if (!current_layer_->clip_bounds.intersect(rect)) {
606+
current_layer_->clip_bounds.setEmpty();
607+
}
608+
break;
609+
case SkClipOp::kDifference:
610+
Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
611+
break;
612+
}
592613
}
593614
void DisplayListBuilder::clipRRect(const SkRRect& rrect,
594615
SkClipOp clip_op,
595616
bool is_aa) {
596617
if (rrect.isRect()) {
597618
clipRect(rrect.rect(), clip_op, is_aa);
598619
} else {
599-
clip_op == SkClipOp::kIntersect //
600-
? Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa)
601-
: Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
620+
switch (clip_op) {
621+
case SkClipOp::kIntersect:
622+
Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa);
623+
if (!current_layer_->clip_bounds.intersect(rrect.getBounds())) {
624+
current_layer_->clip_bounds.setEmpty();
625+
}
626+
break;
627+
case SkClipOp::kDifference:
628+
Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
629+
break;
630+
}
602631
}
603632
}
604633
void DisplayListBuilder::clipPath(const SkPath& path,
@@ -621,9 +650,26 @@ void DisplayListBuilder::clipPath(const SkPath& path,
621650
return;
622651
}
623652
}
624-
clip_op == SkClipOp::kIntersect //
625-
? Push<ClipIntersectPathOp>(0, 1, path, is_aa)
626-
: Push<ClipDifferencePathOp>(0, 1, path, is_aa);
653+
switch (clip_op) {
654+
case SkClipOp::kIntersect:
655+
Push<ClipIntersectPathOp>(0, 1, path, is_aa);
656+
if (!current_layer_->clip_bounds.intersect(path.getBounds())) {
657+
current_layer_->clip_bounds.setEmpty();
658+
}
659+
break;
660+
case SkClipOp::kDifference:
661+
Push<ClipDifferencePathOp>(0, 1, path, is_aa);
662+
break;
663+
}
664+
}
665+
SkRect DisplayListBuilder::getLocalClipBounds() {
666+
SkM44 inverse;
667+
if (current_layer_->matrix.invert(&inverse)) {
668+
SkRect devBounds;
669+
current_layer_->clip_bounds.roundOut(&devBounds);
670+
return inverse.asM33().mapRect(devBounds);
671+
}
672+
return kMaxCullRect_;
627673
}
628674

629675
void DisplayListBuilder::drawPaint() {

display_list/display_list_builder.h

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,28 @@ class DisplayListBuilder final : public virtual Dispatcher,
198198
void transform(const SkMatrix& matrix) { transform(&matrix); }
199199
void transform(const SkM44& matrix44) { transform(&matrix44); }
200200

201+
/// Returns the 4x4 full perspective transform representing all transform
202+
/// operations executed so far in this DisplayList within the enclosing
203+
/// save stack.
204+
SkM44 getTransformFullPerspective() { return current_layer_->matrix; }
205+
/// Returns the 3x3 partial perspective transform representing all transform
206+
/// operations executed so far in this DisplayList within the enclosing
207+
/// save stack.
208+
SkMatrix getTransform() { return current_layer_->matrix.asM33(); }
209+
201210
void clipRect(const SkRect& rect, SkClipOp clip_op, bool is_aa) override;
202211
void clipRRect(const SkRRect& rrect, SkClipOp clip_op, bool is_aa) override;
203212
void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override;
204213

214+
/// Conservative estimate of the bounds of all outstanding clip operations
215+
/// measured in the coordinate space within which this DisplayList will
216+
/// be rendered.
217+
SkRect getDestinationClipBounds() { return current_layer_->clip_bounds; }
218+
/// Conservative estimate of the bounds of all outstanding clip operations
219+
/// transformed into the local coordinate space in which currently
220+
/// recorded rendering operations are interpreted.
221+
SkRect getLocalClipBounds();
222+
205223
void drawPaint() override;
206224
void drawPaint(const DlPaint& paint);
207225
void drawColor(DlColor color, DlBlendMode mode) override;
@@ -350,11 +368,24 @@ class DisplayListBuilder final : public virtual Dispatcher,
350368
}
351369

352370
struct LayerInfo {
353-
LayerInfo(size_t save_layer_offset = 0, bool has_layer = false)
371+
LayerInfo(const SkM44& matrix,
372+
const SkRect& clip_bounds,
373+
size_t save_layer_offset = 0,
374+
bool has_layer = false)
354375
: save_layer_offset(save_layer_offset),
355376
has_layer(has_layer),
356377
cannot_inherit_opacity(false),
357-
has_compatible_op(false) {}
378+
has_compatible_op(false),
379+
matrix(matrix),
380+
clip_bounds(clip_bounds) {}
381+
382+
LayerInfo(const LayerInfo* current_layer,
383+
size_t save_layer_offset = 0,
384+
bool has_layer = false)
385+
: LayerInfo(current_layer->matrix,
386+
current_layer->clip_bounds,
387+
save_layer_offset,
388+
has_layer) {}
358389

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

402+
SkM44 matrix;
403+
SkRect clip_bounds;
404+
371405
bool is_group_opacity_compatible() const { return !cannot_inherit_opacity; }
372406

373407
void mark_incompatible() { cannot_inherit_opacity = true; }

0 commit comments

Comments
 (0)