Use DisplayListMatrixClipTracker in DisplayListBuilder (flutter/engine#38349)
* Use DisplayListMatrixClipTracker in DisplayListBuilder * Ignore is_aa * Revert "Ignore is_aa" This reverts commit b201dadc773f8e726ec68ed88114df9be7b5a9b0. * Tweak code * Use content_culled * getLocalClipBounds without device clip bounds roundsOut * Tweak code and add more tests * remove virtual
This commit is contained in:
@@ -67,16 +67,15 @@ sk_sp<DisplayList> DisplayListBuilder::Build() {
|
||||
}
|
||||
|
||||
DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect,
|
||||
bool prepare_rtree) {
|
||||
bool prepare_rtree)
|
||||
: tracker_(cull_rect, SkMatrix::I()) {
|
||||
if (prepare_rtree) {
|
||||
accumulator_ = std::make_unique<RTreeBoundsAccumulator>();
|
||||
} else {
|
||||
accumulator_ = std::make_unique<RectBoundsAccumulator>();
|
||||
}
|
||||
|
||||
// isEmpty protects us against NaN as we normalize any empty cull rects
|
||||
SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
|
||||
layer_stack_.emplace_back(SkM44(), SkMatrix::I(), cull);
|
||||
layer_stack_.emplace_back();
|
||||
current_layer_ = &layer_stack_.back();
|
||||
}
|
||||
|
||||
@@ -440,9 +439,10 @@ void DisplayListBuilder::checkForDeferredSave() {
|
||||
}
|
||||
|
||||
void DisplayListBuilder::save() {
|
||||
layer_stack_.emplace_back(current_layer_);
|
||||
layer_stack_.emplace_back();
|
||||
current_layer_ = &layer_stack_.back();
|
||||
current_layer_->has_deferred_save_op_ = true;
|
||||
tracker_.save();
|
||||
accumulator()->save();
|
||||
}
|
||||
|
||||
@@ -455,6 +455,7 @@ void DisplayListBuilder::restore() {
|
||||
// on the stack.
|
||||
LayerInfo layer_info = layer_stack_.back();
|
||||
|
||||
tracker_.restore();
|
||||
layer_stack_.pop_back();
|
||||
current_layer_ = &layer_stack_.back();
|
||||
bool is_unbounded = layer_info.is_unbounded();
|
||||
@@ -463,7 +464,7 @@ void DisplayListBuilder::restore() {
|
||||
// current accumulator and adjust it as required based on the filter.
|
||||
std::shared_ptr<const DlImageFilter> filter = layer_info.filter();
|
||||
if (filter) {
|
||||
const SkRect* clip = ¤t_layer_->clip_bounds();
|
||||
const SkRect clip = tracker_.device_cull_rect();
|
||||
if (!accumulator()->restore(
|
||||
[filter = filter, matrix = getTransform()](const SkRect& input,
|
||||
SkRect& output) {
|
||||
@@ -473,7 +474,7 @@ void DisplayListBuilder::restore() {
|
||||
output.set(output_bounds);
|
||||
return ret;
|
||||
},
|
||||
clip)) {
|
||||
&clip)) {
|
||||
is_unbounded = true;
|
||||
}
|
||||
} else {
|
||||
@@ -544,11 +545,12 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
|
||||
// We will fill the clip of the outer layer when we restore
|
||||
AccumulateUnbounded();
|
||||
}
|
||||
layer_stack_.emplace_back(current_layer_, save_layer_offset, true,
|
||||
layer_stack_.emplace_back(save_layer_offset, true,
|
||||
current_.getImageFilter());
|
||||
} else {
|
||||
layer_stack_.emplace_back(current_layer_, save_layer_offset, true, nullptr);
|
||||
layer_stack_.emplace_back(save_layer_offset, true, nullptr);
|
||||
}
|
||||
tracker_.save();
|
||||
accumulator()->save();
|
||||
current_layer_ = &layer_stack_.back();
|
||||
if (options.renders_with_attributes()) {
|
||||
@@ -566,7 +568,7 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
|
||||
// use them as the temporary layer bounds during rendering the layer, so
|
||||
// we set them as if a clip operation were performed.
|
||||
if (bounds) {
|
||||
intersect(*bounds);
|
||||
tracker_.clipRect(*bounds, SkClipOp::kIntersect, false);
|
||||
}
|
||||
if (backdrop) {
|
||||
// A backdrop will affect up to the entire surface, bounded by the clip
|
||||
@@ -590,8 +592,7 @@ void DisplayListBuilder::translate(SkScalar tx, SkScalar ty) {
|
||||
(tx != 0.0 || ty != 0.0)) {
|
||||
checkForDeferredSave();
|
||||
Push<TranslateOp>(0, 1, tx, ty);
|
||||
current_layer_->matrix().preTranslate(tx, ty);
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.translate(tx, ty);
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) {
|
||||
@@ -599,16 +600,14 @@ void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) {
|
||||
(sx != 1.0 || sy != 1.0)) {
|
||||
checkForDeferredSave();
|
||||
Push<ScaleOp>(0, 1, sx, sy);
|
||||
current_layer_->matrix().preScale(sx, sy);
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.scale(sx, sy);
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::rotate(SkScalar degrees) {
|
||||
if (SkScalarMod(degrees, 360.0) != 0.0) {
|
||||
checkForDeferredSave();
|
||||
Push<RotateOp>(0, 1, degrees);
|
||||
current_layer_->matrix().preConcat(SkMatrix::RotateDeg(degrees));
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.rotate(degrees);
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) {
|
||||
@@ -616,8 +615,7 @@ void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) {
|
||||
(sx != 0.0 || sy != 0.0)) {
|
||||
checkForDeferredSave();
|
||||
Push<SkewOp>(0, 1, sx, sy);
|
||||
current_layer_->matrix().preConcat(SkMatrix::Skew(sx, sy));
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.skew(sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,11 +634,8 @@ 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));
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.transform2DAffine(mxx, mxy, mxt,
|
||||
myx, myy, myt);
|
||||
}
|
||||
}
|
||||
// full 4x4 transform in row major order
|
||||
@@ -665,19 +660,17 @@ 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));
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.transformFullPerspective(mxx, mxy, mxz, mxt,
|
||||
myx, myy, myz, myt,
|
||||
mzx, mzy, mzz, mzt,
|
||||
mwx, mwy, mwz, mwt);
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
void DisplayListBuilder::transformReset() {
|
||||
checkForDeferredSave();
|
||||
Push<TransformResetOp>(0, 0);
|
||||
current_layer_->matrix().setIdentity();
|
||||
current_layer_->update_matrix33();
|
||||
tracker_.setIdentity();
|
||||
}
|
||||
void DisplayListBuilder::transform(const SkMatrix* matrix) {
|
||||
if (matrix != nullptr) {
|
||||
@@ -704,12 +697,12 @@ void DisplayListBuilder::clipRect(const SkRect& rect,
|
||||
switch (clip_op) {
|
||||
case SkClipOp::kIntersect:
|
||||
Push<ClipIntersectRectOp>(0, 1, rect, is_aa);
|
||||
intersect(rect);
|
||||
break;
|
||||
case SkClipOp::kDifference:
|
||||
Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
|
||||
break;
|
||||
}
|
||||
tracker_.clipRect(rect, clip_op, is_aa);
|
||||
}
|
||||
void DisplayListBuilder::clipRRect(const SkRRect& rrect,
|
||||
SkClipOp clip_op,
|
||||
@@ -721,12 +714,12 @@ void DisplayListBuilder::clipRRect(const SkRRect& rrect,
|
||||
switch (clip_op) {
|
||||
case SkClipOp::kIntersect:
|
||||
Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa);
|
||||
intersect(rrect.getBounds());
|
||||
break;
|
||||
case SkClipOp::kDifference:
|
||||
Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
|
||||
break;
|
||||
}
|
||||
tracker_.clipRRect(rrect, clip_op, is_aa);
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::clipPath(const SkPath& path,
|
||||
@@ -753,48 +746,16 @@ void DisplayListBuilder::clipPath(const SkPath& path,
|
||||
switch (clip_op) {
|
||||
case SkClipOp::kIntersect:
|
||||
Push<ClipIntersectPathOp>(0, 1, path, is_aa);
|
||||
if (!path.isInverseFillType()) {
|
||||
intersect(path.getBounds());
|
||||
}
|
||||
break;
|
||||
case SkClipOp::kDifference:
|
||||
Push<ClipDifferencePathOp>(0, 1, path, is_aa);
|
||||
// Map "kDifference of inverse path" to "kIntersect of the original path".
|
||||
if (path.isInverseFillType()) {
|
||||
intersect(path.getBounds());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::intersect(const SkRect& rect) {
|
||||
SkRect dev_clip_bounds = getTransform().mapRect(rect);
|
||||
if (!current_layer_->clip_bounds().intersect(dev_clip_bounds)) {
|
||||
current_layer_->clip_bounds().setEmpty();
|
||||
}
|
||||
}
|
||||
SkRect DisplayListBuilder::getLocalClipBounds() {
|
||||
SkM44 inverse;
|
||||
if (current_layer_->matrix().invert(&inverse)) {
|
||||
SkRect dev_bounds;
|
||||
current_layer_->clip_bounds().roundOut(&dev_bounds);
|
||||
return inverse.asM33().mapRect(dev_bounds);
|
||||
}
|
||||
return kMaxCullRect;
|
||||
tracker_.clipPath(path, clip_op, is_aa);
|
||||
}
|
||||
|
||||
bool DisplayListBuilder::quickReject(const SkRect& bounds) const {
|
||||
if (bounds.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
SkMatrix matrix = getTransform();
|
||||
// We don't need the inverse, but this method tells us if the matrix
|
||||
// is singular in which case we can reject all rendering.
|
||||
if (!matrix.invert(nullptr)) {
|
||||
return true;
|
||||
}
|
||||
SkRect dev_bounds;
|
||||
matrix.mapRect(bounds).roundOut(&dev_bounds);
|
||||
return !current_layer_->clip_bounds().intersects(dev_bounds);
|
||||
return tracker_.content_culled(bounds);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::drawPaint() {
|
||||
@@ -1357,7 +1318,7 @@ bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds,
|
||||
}
|
||||
|
||||
void DisplayListBuilder::AccumulateUnbounded() {
|
||||
accumulator()->accumulate(current_layer_->clip_bounds());
|
||||
accumulator()->accumulate(tracker_.device_cull_rect());
|
||||
}
|
||||
|
||||
void DisplayListBuilder::AccumulateOpBounds(SkRect& bounds,
|
||||
@@ -1369,8 +1330,8 @@ void DisplayListBuilder::AccumulateOpBounds(SkRect& bounds,
|
||||
}
|
||||
}
|
||||
void DisplayListBuilder::AccumulateBounds(SkRect& bounds) {
|
||||
getTransform().mapRect(&bounds);
|
||||
if (bounds.intersect(current_layer_->clip_bounds())) {
|
||||
tracker_.mapRect(&bounds);
|
||||
if (bounds.intersect(tracker_.device_cull_rect())) {
|
||||
accumulator()->accumulate(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_flags.h"
|
||||
#include "flutter/display_list/display_list_image.h"
|
||||
#include "flutter/display_list/display_list_matrix_clip_tracker.h"
|
||||
#include "flutter/display_list/display_list_paint.h"
|
||||
#include "flutter/display_list/display_list_path_effect.h"
|
||||
#include "flutter/display_list/display_list_sampling_options.h"
|
||||
@@ -210,11 +211,11 @@ class DisplayListBuilder final : public virtual Dispatcher,
|
||||
/// Returns the 4x4 full perspective transform representing all transform
|
||||
/// operations executed so far in this DisplayList within the enclosing
|
||||
/// save stack.
|
||||
SkM44 getTransformFullPerspective() const { return current_layer_->matrix(); }
|
||||
SkM44 getTransformFullPerspective() const { return tracker_.matrix_4x4(); }
|
||||
/// Returns the 3x3 partial perspective transform representing all transform
|
||||
/// operations executed so far in this DisplayList within the enclosing
|
||||
/// save stack.
|
||||
SkMatrix getTransform() const { return current_layer_->matrix33(); }
|
||||
SkMatrix getTransform() const { return tracker_.matrix_3x3(); }
|
||||
|
||||
void clipRect(const SkRect& rect, SkClipOp clip_op, bool is_aa) override;
|
||||
void clipRRect(const SkRRect& rrect, SkClipOp clip_op, bool is_aa) override;
|
||||
@@ -223,11 +224,11 @@ class DisplayListBuilder final : public virtual Dispatcher,
|
||||
/// 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(); }
|
||||
SkRect getDestinationClipBounds() { return tracker_.device_cull_rect(); }
|
||||
/// 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();
|
||||
SkRect getLocalClipBounds() { return tracker_.local_cull_rect(); }
|
||||
|
||||
/// Return true iff the supplied bounds are easily shown to be outside
|
||||
/// of the current clip bounds. This method may conservatively return
|
||||
@@ -386,33 +387,16 @@ class DisplayListBuilder final : public virtual Dispatcher,
|
||||
|
||||
class LayerInfo {
|
||||
public:
|
||||
explicit LayerInfo(const SkM44& matrix,
|
||||
const SkMatrix& matrix33,
|
||||
const SkRect& clip_bounds,
|
||||
size_t save_layer_offset = 0,
|
||||
explicit LayerInfo(size_t save_layer_offset = 0,
|
||||
bool has_layer = false,
|
||||
std::shared_ptr<const DlImageFilter> filter = nullptr)
|
||||
: save_layer_offset_(save_layer_offset),
|
||||
has_layer_(has_layer),
|
||||
cannot_inherit_opacity_(false),
|
||||
has_compatible_op_(false),
|
||||
matrix_(matrix),
|
||||
matrix33_(matrix33),
|
||||
clip_bounds_(clip_bounds),
|
||||
filter_(filter),
|
||||
is_unbounded_(false) {}
|
||||
|
||||
explicit LayerInfo(const LayerInfo* current_layer,
|
||||
size_t save_layer_offset = 0,
|
||||
bool has_layer = false,
|
||||
std::shared_ptr<const DlImageFilter> filter = nullptr)
|
||||
: LayerInfo(current_layer->matrix_,
|
||||
current_layer->matrix33_,
|
||||
current_layer->clip_bounds_,
|
||||
save_layer_offset,
|
||||
has_layer,
|
||||
filter) {}
|
||||
|
||||
// The offset into the memory buffer where the saveLayer DLOp record
|
||||
// for this saveLayer() call is placed. This may be needed if the
|
||||
// eventual restore() call has discovered important information about
|
||||
@@ -424,11 +408,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
|
||||
bool has_layer() const { return has_layer_; }
|
||||
bool cannot_inherit_opacity() const { return cannot_inherit_opacity_; }
|
||||
bool has_compatible_op() const { return cannot_inherit_opacity_; }
|
||||
SkM44& matrix() { return matrix_; }
|
||||
SkMatrix& matrix33() { return matrix33_; }
|
||||
SkRect& clip_bounds() { return clip_bounds_; }
|
||||
|
||||
void update_matrix33() { matrix33_ = matrix_.asM33(); }
|
||||
|
||||
bool is_group_opacity_compatible() const {
|
||||
return !cannot_inherit_opacity_;
|
||||
@@ -486,9 +465,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
|
||||
bool has_layer_;
|
||||
bool cannot_inherit_opacity_;
|
||||
bool has_compatible_op_;
|
||||
SkM44 matrix_;
|
||||
SkMatrix matrix33_;
|
||||
SkRect clip_bounds_;
|
||||
std::shared_ptr<const DlImageFilter> filter_;
|
||||
bool is_unbounded_;
|
||||
bool has_deferred_save_op_ = false;
|
||||
@@ -498,6 +474,7 @@ class DisplayListBuilder final : public virtual Dispatcher,
|
||||
|
||||
std::vector<LayerInfo> layer_stack_;
|
||||
LayerInfo* current_layer_;
|
||||
DisplayListMatrixClipTracker tracker_;
|
||||
std::unique_ptr<BoundsAccumulator> accumulator_;
|
||||
BoundsAccumulator* accumulator() { return accumulator_.get(); }
|
||||
|
||||
|
||||
@@ -39,12 +39,13 @@ class Data4x4 : public DisplayListMatrixClipTracker::Data {
|
||||
void setTransform(const SkMatrix& matrix) override { m44_ = SkM44(matrix); }
|
||||
void setTransform(const SkM44& m44) override { m44_ = m44; }
|
||||
void setIdentity() override { m44_.setIdentity(); }
|
||||
bool mapRect(const SkRect& rect, SkRect* mapped) const override {
|
||||
return m44_.asM33().mapRect(mapped, rect);
|
||||
}
|
||||
bool canBeInverted() const override { return m44_.asM33().invert(nullptr); }
|
||||
|
||||
protected:
|
||||
bool has_perspective() const override;
|
||||
bool map_rect(const SkRect& rect, SkRect* mapped) const override {
|
||||
return m44_.asM33().mapRect(mapped, rect);
|
||||
}
|
||||
|
||||
private:
|
||||
SkM44 m44_;
|
||||
@@ -80,12 +81,13 @@ class Data3x3 : public DisplayListMatrixClipTracker::Data {
|
||||
FML_CHECK(false) << "SkM44 was set without upgrading Data";
|
||||
}
|
||||
void setIdentity() override { matrix_.setIdentity(); }
|
||||
bool mapRect(const SkRect& rect, SkRect* mapped) const override {
|
||||
return matrix_.mapRect(mapped, rect);
|
||||
}
|
||||
bool canBeInverted() const override { return matrix_.invert(nullptr); }
|
||||
|
||||
protected:
|
||||
bool has_perspective() const override { return matrix_.hasPerspective(); }
|
||||
bool map_rect(const SkRect& rect, SkRect* mapped) const override {
|
||||
return matrix_.mapRect(mapped, rect);
|
||||
}
|
||||
|
||||
private:
|
||||
SkMatrix matrix_;
|
||||
@@ -103,21 +105,64 @@ static bool is_3x3(const SkM44& m) {
|
||||
DisplayListMatrixClipTracker::DisplayListMatrixClipTracker(
|
||||
const SkRect& cull_rect,
|
||||
const SkMatrix& matrix) {
|
||||
saved_.emplace_back(std::make_unique<Data3x3>(matrix, cull_rect));
|
||||
// isEmpty protects us against NaN as we normalize any empty cull rects
|
||||
SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
|
||||
saved_.emplace_back(std::make_unique<Data3x3>(matrix, cull));
|
||||
current_ = saved_.back().get();
|
||||
}
|
||||
|
||||
DisplayListMatrixClipTracker::DisplayListMatrixClipTracker(
|
||||
const SkRect& cull_rect,
|
||||
const SkM44& m44) {
|
||||
// isEmpty protects us against NaN as we normalize any empty cull rects
|
||||
SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
|
||||
if (is_3x3(m44)) {
|
||||
saved_.emplace_back(std::make_unique<Data3x3>(m44.asM33(), cull_rect));
|
||||
saved_.emplace_back(std::make_unique<Data3x3>(m44.asM33(), cull));
|
||||
} else {
|
||||
saved_.emplace_back(std::make_unique<Data4x4>(m44, cull_rect));
|
||||
saved_.emplace_back(std::make_unique<Data4x4>(m44, cull));
|
||||
}
|
||||
current_ = saved_.back().get();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
void DisplayListMatrixClipTracker::transform2DAffine(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt) {
|
||||
if (!current_->is_4x4()) {
|
||||
transform(SkMatrix::MakeAll(mxx, mxy, mxt,
|
||||
myx, myy, myt,
|
||||
0, 0, 1));
|
||||
} else {
|
||||
transform(SkM44(mxx, mxy, 0, mxt,
|
||||
myx, myy, 0, myt,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1));
|
||||
}
|
||||
}
|
||||
void DisplayListMatrixClipTracker::transformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
|
||||
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
|
||||
if (!current_->is_4x4()) {
|
||||
if ( mxz == 0 &&
|
||||
myz == 0 &&
|
||||
mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
|
||||
mwz == 0) {
|
||||
transform(SkMatrix::MakeAll(mxx, mxy, mxt,
|
||||
myx, myy, myt,
|
||||
mwx, mwy, mwt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
transform(SkM44(mxx, mxy, mxz, mxt,
|
||||
myx, myy, myz, myt,
|
||||
mzx, mzy, mzz, mzt,
|
||||
mwx, mwy, mwz, mwt));
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
void DisplayListMatrixClipTracker::save() {
|
||||
if (current_->is_4x4()) {
|
||||
saved_.emplace_back(std::make_unique<Data4x4>(current_));
|
||||
@@ -183,6 +228,19 @@ void DisplayListMatrixClipTracker::clipRRect(const SkRRect& rrect,
|
||||
void DisplayListMatrixClipTracker::clipPath(const SkPath& path,
|
||||
SkClipOp op,
|
||||
bool is_aa) {
|
||||
// Map "kDifference of inverse path" to "kIntersect of the original path" and
|
||||
// map "kIntersect of inverse path" to "kDifference of the original path"
|
||||
if (path.isInverseFillType()) {
|
||||
switch (op) {
|
||||
case SkClipOp::kIntersect:
|
||||
op = SkClipOp::kDifference;
|
||||
break;
|
||||
case SkClipOp::kDifference:
|
||||
op = SkClipOp::kIntersect;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SkRect bounds;
|
||||
switch (op) {
|
||||
case SkClipOp::kIntersect:
|
||||
@@ -202,11 +260,14 @@ bool DisplayListMatrixClipTracker::Data::content_culled(
|
||||
if (cull_rect_.isEmpty() || content_bounds.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (!canBeInverted()) {
|
||||
return true;
|
||||
}
|
||||
if (has_perspective()) {
|
||||
return false;
|
||||
}
|
||||
SkRect mapped;
|
||||
map_rect(content_bounds, &mapped);
|
||||
mapRect(content_bounds, &mapped);
|
||||
return !mapped.intersects(cull_rect_);
|
||||
}
|
||||
|
||||
@@ -228,7 +289,7 @@ void DisplayListMatrixClipTracker::Data::clipBounds(const SkRect& clip,
|
||||
break;
|
||||
}
|
||||
SkRect rect;
|
||||
map_rect(clip, &rect);
|
||||
mapRect(clip, &rect);
|
||||
if (is_aa) {
|
||||
rect.roundOut(&rect);
|
||||
}
|
||||
@@ -242,7 +303,7 @@ void DisplayListMatrixClipTracker::Data::clipBounds(const SkRect& clip,
|
||||
break;
|
||||
}
|
||||
SkRect rect;
|
||||
if (map_rect(clip, &rect)) {
|
||||
if (mapRect(clip, &rect)) {
|
||||
// This technique only works if it is rect -> rect
|
||||
if (is_aa) {
|
||||
SkIRect rounded;
|
||||
|
||||
@@ -44,9 +44,20 @@ class DisplayListMatrixClipTracker {
|
||||
void rotate(SkScalar degrees) { current_->rotate(degrees); }
|
||||
void transform(const SkM44& m44);
|
||||
void transform(const SkMatrix& matrix) { current_->transform(matrix); }
|
||||
// clang-format off
|
||||
void transform2DAffine(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt);
|
||||
void transformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
|
||||
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt);
|
||||
// clang-format on
|
||||
void setTransform(const SkMatrix& matrix) { current_->setTransform(matrix); }
|
||||
void setTransform(const SkM44& m44);
|
||||
void setIdentity() { current_->setIdentity(); }
|
||||
bool mapRect(SkRect* rect) const { return current_->mapRect(*rect, rect); }
|
||||
|
||||
void clipRect(const SkRect& rect, SkClipOp op, bool is_aa) {
|
||||
current_->clipBounds(rect, op, is_aa);
|
||||
@@ -77,6 +88,8 @@ class DisplayListMatrixClipTracker {
|
||||
virtual void setTransform(const SkMatrix& matrix) = 0;
|
||||
virtual void setTransform(const SkM44& m44) = 0;
|
||||
virtual void setIdentity() = 0;
|
||||
virtual bool mapRect(const SkRect& rect, SkRect* mapped) const = 0;
|
||||
virtual bool canBeInverted() const = 0;
|
||||
|
||||
virtual void clipBounds(const SkRect& clip, SkClipOp op, bool is_aa);
|
||||
|
||||
@@ -84,7 +97,6 @@ class DisplayListMatrixClipTracker {
|
||||
Data(const SkRect& rect) : cull_rect_(rect) {}
|
||||
|
||||
virtual bool has_perspective() const = 0;
|
||||
virtual bool map_rect(const SkRect& rect, SkRect* mapped) const = 0;
|
||||
|
||||
SkRect cull_rect_;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "flutter/display_list/display_list_matrix_clip_tracker.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
@@ -225,5 +226,127 @@ TEST(DisplayListMatrixClipTracker, Rotate) {
|
||||
ASSERT_EQ(tracker2.matrix_4x4(), rotated_m44);
|
||||
}
|
||||
|
||||
TEST(DisplayListMatrixClipTracker, Transform2DAffine) {
|
||||
const SkRect cull_rect = SkRect::MakeLTRB(20, 20, 60, 60);
|
||||
const SkMatrix matrix = SkMatrix::Scale(4, 4);
|
||||
const SkM44 m44 = SkM44::Scale(4, 4);
|
||||
|
||||
const SkMatrix transformed_matrix =
|
||||
SkMatrix::Concat(matrix, SkMatrix::MakeAll(2, 0, 5, //
|
||||
0, 2, 6, //
|
||||
0, 0, 1));
|
||||
const SkM44 transformed_m44 = SkM44(transformed_matrix);
|
||||
const SkRect local_cull_rect = SkRect::MakeLTRB(0, -0.5, 5, 4.5);
|
||||
|
||||
DisplayListMatrixClipTracker tracker1(cull_rect, matrix);
|
||||
DisplayListMatrixClipTracker tracker2(cull_rect, m44);
|
||||
tracker1.transform2DAffine(2, 0, 5, //
|
||||
0, 2, 6);
|
||||
tracker2.transform2DAffine(2, 0, 5, //
|
||||
0, 2, 6);
|
||||
ASSERT_FALSE(tracker1.using_4x4_matrix());
|
||||
ASSERT_EQ(tracker1.device_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(tracker1.local_cull_rect(), local_cull_rect);
|
||||
ASSERT_EQ(tracker1.matrix_3x3(), transformed_matrix);
|
||||
ASSERT_EQ(tracker1.matrix_4x4(), transformed_m44);
|
||||
|
||||
ASSERT_FALSE(tracker2.using_4x4_matrix());
|
||||
ASSERT_EQ(tracker2.device_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(tracker2.local_cull_rect(), local_cull_rect);
|
||||
ASSERT_EQ(tracker2.matrix_3x3(), transformed_matrix);
|
||||
ASSERT_EQ(tracker2.matrix_4x4(), transformed_m44);
|
||||
}
|
||||
|
||||
TEST(DisplayListMatrixClipTracker, TransformFullPerspectiveUsing3x3Matrix) {
|
||||
const SkRect cull_rect = SkRect::MakeLTRB(20, 20, 60, 60);
|
||||
const SkMatrix matrix = SkMatrix::Scale(4, 4);
|
||||
const SkM44 m44 = SkM44::Scale(4, 4);
|
||||
|
||||
const SkMatrix transformed_matrix =
|
||||
SkMatrix::Concat(matrix, SkMatrix::MakeAll(2, 0, 5, //
|
||||
0, 2, 6, //
|
||||
0, 0, 1));
|
||||
const SkM44 transformed_m44 = SkM44(transformed_matrix);
|
||||
const SkRect local_cull_rect = SkRect::MakeLTRB(0, -0.5, 5, 4.5);
|
||||
|
||||
DisplayListMatrixClipTracker tracker1(cull_rect, matrix);
|
||||
DisplayListMatrixClipTracker tracker2(cull_rect, m44);
|
||||
tracker1.transformFullPerspective(2, 0, 0, 5, //
|
||||
0, 2, 0, 6, //
|
||||
0, 0, 1, 0, //
|
||||
0, 0, 0, 1);
|
||||
tracker2.transformFullPerspective(2, 0, 0, 5, //
|
||||
0, 2, 0, 6, //
|
||||
0, 0, 1, 0, //
|
||||
0, 0, 0, 1);
|
||||
ASSERT_FALSE(tracker1.using_4x4_matrix());
|
||||
ASSERT_EQ(tracker1.device_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(tracker1.local_cull_rect(), local_cull_rect);
|
||||
ASSERT_EQ(tracker1.matrix_3x3(), transformed_matrix);
|
||||
ASSERT_EQ(tracker1.matrix_4x4(), transformed_m44);
|
||||
|
||||
ASSERT_FALSE(tracker2.using_4x4_matrix());
|
||||
ASSERT_EQ(tracker2.device_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(tracker2.local_cull_rect(), local_cull_rect);
|
||||
ASSERT_EQ(tracker2.matrix_3x3(), transformed_matrix);
|
||||
ASSERT_EQ(tracker2.matrix_4x4(), transformed_m44);
|
||||
}
|
||||
|
||||
TEST(DisplayListMatrixClipTracker, TransformFullPerspectiveUsing4x4Matrix) {
|
||||
const SkRect cull_rect = SkRect::MakeLTRB(20, 20, 60, 60);
|
||||
const SkMatrix matrix = SkMatrix::Scale(4, 4);
|
||||
const SkM44 m44 = SkM44::Scale(4, 4);
|
||||
|
||||
const SkM44 transformed_m44 = SkM44(m44, SkM44(2, 0, 0, 5, //
|
||||
0, 2, 0, 6, //
|
||||
0, 0, 1, 7, //
|
||||
0, 0, 0, 1));
|
||||
const SkRect local_cull_rect = SkRect::MakeLTRB(0, -0.5, 5, 4.5);
|
||||
|
||||
DisplayListMatrixClipTracker tracker1(cull_rect, matrix);
|
||||
DisplayListMatrixClipTracker tracker2(cull_rect, m44);
|
||||
tracker1.transformFullPerspective(2, 0, 0, 5, //
|
||||
0, 2, 0, 6, //
|
||||
0, 0, 1, 7, //
|
||||
0, 0, 0, 1);
|
||||
tracker2.transformFullPerspective(2, 0, 0, 5, //
|
||||
0, 2, 0, 6, //
|
||||
0, 0, 1, 7, //
|
||||
0, 0, 0, 1);
|
||||
ASSERT_TRUE(tracker1.using_4x4_matrix());
|
||||
ASSERT_EQ(tracker1.device_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(tracker1.local_cull_rect(), local_cull_rect);
|
||||
ASSERT_EQ(tracker1.matrix_4x4(), transformed_m44);
|
||||
|
||||
ASSERT_TRUE(tracker2.using_4x4_matrix());
|
||||
ASSERT_EQ(tracker2.device_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(tracker2.local_cull_rect(), local_cull_rect);
|
||||
ASSERT_EQ(tracker2.matrix_4x4(), transformed_m44);
|
||||
}
|
||||
|
||||
TEST(DisplayListMatrixClipTracker, ClipPathWithInvertFillType) {
|
||||
SkRect cull_rect = SkRect::MakeLTRB(0, 0, 100.0, 100.0);
|
||||
DisplayListMatrixClipTracker builder(cull_rect, SkMatrix::I());
|
||||
SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
|
||||
clip.setFillType(SkPathFillType::kInverseWinding);
|
||||
builder.clipPath(clip, SkClipOp::kIntersect, false);
|
||||
|
||||
ASSERT_EQ(builder.local_cull_rect(), cull_rect);
|
||||
ASSERT_EQ(builder.device_cull_rect(), cull_rect);
|
||||
}
|
||||
|
||||
TEST(DisplayListMatrixClipTracker, DiffClipPathWithInvertFillType) {
|
||||
SkRect cull_rect = SkRect::MakeLTRB(0, 0, 100.0, 100.0);
|
||||
DisplayListMatrixClipTracker tracker(cull_rect, SkMatrix::I());
|
||||
|
||||
SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
|
||||
clip.setFillType(SkPathFillType::kInverseWinding);
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7);
|
||||
tracker.clipPath(clip, SkClipOp::kDifference, false);
|
||||
|
||||
ASSERT_EQ(tracker.local_cull_rect(), clip_bounds);
|
||||
ASSERT_EQ(tracker.device_cull_rect(), clip_bounds);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@@ -1361,22 +1361,21 @@ TEST(DisplayList, FullTransformAffectsCurrentTransform) {
|
||||
TEST(DisplayList, ClipRectAffectsClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26);
|
||||
builder.clipRect(clip_bounds, SkClipOp::kIntersect, false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.clipRect({0, 0, 15, 15}, SkClipOp::kIntersect, false);
|
||||
// Both clip bounds have changed
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_bounds);
|
||||
ASSERT_NE(builder.getDestinationClipBounds(), clip_bounds);
|
||||
// Previous return values have not changed
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
builder.restore();
|
||||
|
||||
@@ -1384,12 +1383,51 @@ TEST(DisplayList, ClipRectAffectsClipBounds) {
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.scale(2, 2);
|
||||
SkRect scaled_clip_bounds = SkRect::MakeLTRB(5.1, 5.65, 10.2, 12.85);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), scaled_clip_bounds);
|
||||
// Destination bounds are unaffected by transform
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
}
|
||||
|
||||
TEST(DisplayList, ClipRectDoAAAffectsClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26);
|
||||
builder.clipRect(clip_bounds, SkClipOp::kIntersect, true);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.clipRect({0, 0, 15, 15}, SkClipOp::kIntersect, true);
|
||||
// Both clip bounds have changed
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_NE(builder.getDestinationClipBounds(), clip_expanded_bounds);
|
||||
// Previous return values have not changed
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.scale(2, 2);
|
||||
SkRect scaled_expanded_bounds = SkRect::MakeLTRB(5, 5.5, 10.5, 13);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), scaled_expanded_bounds);
|
||||
// Destination bounds are unaffected by transform
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_expanded_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
@@ -1419,23 +1457,22 @@ TEST(DisplayList, ClipRectAffectsClipBoundsWithMatrix) {
|
||||
TEST(DisplayList, ClipRRectAffectsClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26);
|
||||
SkRRect clip = SkRRect::MakeRectXY(clip_bounds, 3, 2);
|
||||
builder.clipRRect(clip, SkClipOp::kIntersect, false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.clipRect({0, 0, 15, 15}, SkClipOp::kIntersect, false);
|
||||
// Both clip bounds have changed
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_bounds);
|
||||
ASSERT_NE(builder.getDestinationClipBounds(), clip_bounds);
|
||||
// Previous return values have not changed
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
builder.restore();
|
||||
|
||||
@@ -1443,12 +1480,52 @@ TEST(DisplayList, ClipRRectAffectsClipBounds) {
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.scale(2, 2);
|
||||
SkRect scaled_clip_bounds = SkRect::MakeLTRB(5.1, 5.65, 10.2, 12.85);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), scaled_clip_bounds);
|
||||
// Destination bounds are unaffected by transform
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
}
|
||||
|
||||
TEST(DisplayList, ClipRRectDoAAAffectsClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26);
|
||||
SkRRect clip = SkRRect::MakeRectXY(clip_bounds, 3, 2);
|
||||
builder.clipRRect(clip, SkClipOp::kIntersect, true);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.clipRect({0, 0, 15, 15}, SkClipOp::kIntersect, true);
|
||||
// Both clip bounds have changed
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_NE(builder.getDestinationClipBounds(), clip_expanded_bounds);
|
||||
// Previous return values have not changed
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.scale(2, 2);
|
||||
SkRect scaled_expanded_bounds = SkRect::MakeLTRB(5, 5.5, 10.5, 13);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), scaled_expanded_bounds);
|
||||
// Destination bounds are unaffected by transform
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_expanded_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
@@ -1482,22 +1559,21 @@ TEST(DisplayList, ClipPathAffectsClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(8, 9, 23, 28);
|
||||
builder.clipPath(clip, SkClipOp::kIntersect, false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.clipRect({0, 0, 15, 15}, SkClipOp::kIntersect, false);
|
||||
// Both clip bounds have changed
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_bounds);
|
||||
ASSERT_NE(builder.getDestinationClipBounds(), clip_bounds);
|
||||
// Previous return values have not changed
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
builder.restore();
|
||||
|
||||
@@ -1505,12 +1581,51 @@ TEST(DisplayList, ClipPathAffectsClipBounds) {
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.scale(2, 2);
|
||||
SkRect scaled_clip_bounds = SkRect::MakeLTRB(4.1, 4.65, 11.2, 13.85);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), scaled_clip_bounds);
|
||||
// Destination bounds are unaffected by transform
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
}
|
||||
|
||||
TEST(DisplayList, ClipPathDoAAAffectsClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(8, 9, 23, 28);
|
||||
builder.clipPath(clip, SkClipOp::kIntersect, true);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.clipRect({0, 0, 15, 15}, SkClipOp::kIntersect, true);
|
||||
// Both clip bounds have changed
|
||||
ASSERT_NE(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_NE(builder.getDestinationClipBounds(), clip_expanded_bounds);
|
||||
// Previous return values have not changed
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), initial_local_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), initial_destination_bounds);
|
||||
|
||||
builder.save();
|
||||
builder.scale(2, 2);
|
||||
SkRect scaled_expanded_bounds = SkRect::MakeLTRB(4, 4.5, 11.5, 14);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), scaled_expanded_bounds);
|
||||
// Destination bounds are unaffected by transform
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_expanded_bounds);
|
||||
builder.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
@@ -1543,13 +1658,12 @@ TEST(DisplayList, DiffClipRectDoesNotAffectClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkRect diff_clip = SkRect::MakeLTRB(0, 0, 15, 15);
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26);
|
||||
builder.clipRect(clip_bounds, SkClipOp::kIntersect, false);
|
||||
|
||||
// Save initial return values for testing after kDifference clip
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
|
||||
builder.clipRect(diff_clip, SkClipOp::kDifference, false);
|
||||
@@ -1561,14 +1675,13 @@ TEST(DisplayList, DiffClipRRectDoesNotAffectClipBounds) {
|
||||
DisplayListBuilder builder;
|
||||
SkRRect diff_clip = SkRRect::MakeRectXY({0, 0, 15, 15}, 1, 1);
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26);
|
||||
SkRRect clip = SkRRect::MakeRectXY({10.2, 11.3, 20.4, 25.7}, 3, 2);
|
||||
builder.clipRRect(clip, SkClipOp::kIntersect, false);
|
||||
|
||||
// Save initial return values for testing after kDifference clip
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
|
||||
builder.clipRRect(diff_clip, SkClipOp::kDifference, false);
|
||||
@@ -1581,13 +1694,12 @@ TEST(DisplayList, DiffClipPathDoesNotAffectClipBounds) {
|
||||
SkPath diff_clip = SkPath().addRect({0, 0, 15, 15});
|
||||
SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(8, 9, 23, 28);
|
||||
builder.clipPath(clip, SkClipOp::kIntersect, false);
|
||||
|
||||
// Save initial return values for testing after kDifference clip
|
||||
SkRect initial_local_bounds = builder.getLocalClipBounds();
|
||||
SkRect initial_destination_bounds = builder.getDestinationClipBounds();
|
||||
ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
|
||||
ASSERT_EQ(initial_local_bounds, clip_bounds);
|
||||
ASSERT_EQ(initial_destination_bounds, clip_bounds);
|
||||
|
||||
builder.clipPath(diff_clip, SkClipOp::kDifference, false);
|
||||
@@ -1612,10 +1724,9 @@ TEST(DisplayList, DiffClipPathWithInvertFillTypeAffectsClipBounds) {
|
||||
SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2);
|
||||
clip.setFillType(SkPathFillType::kInverseWinding);
|
||||
SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7);
|
||||
SkRect clip_expanded_bounds = SkRect::MakeLTRB(8, 9, 23, 28);
|
||||
builder.clipPath(clip, SkClipOp::kDifference, false);
|
||||
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), clip_expanded_bounds);
|
||||
ASSERT_EQ(builder.getLocalClipBounds(), clip_bounds);
|
||||
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
|
||||
}
|
||||
|
||||
|
||||
@@ -726,7 +726,7 @@ void main() {
|
||||
Expect.fail('$value is too close to $expected');
|
||||
};
|
||||
|
||||
test('Canvas.clipRect affects canvas.getClipBounds', () async {
|
||||
test('Canvas.clipRect(doAA=true) affects canvas.getClipBounds', () async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
@@ -737,16 +737,16 @@ void main() {
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipExpandedBounds));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15));
|
||||
// Both clip bounds have changed
|
||||
expect(canvas.getLocalClipBounds(), notCloseToRect(clipExpandedBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipExpandedBounds));
|
||||
// Previous return values have not changed
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipExpandedBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
@@ -758,6 +758,45 @@ void main() {
|
||||
const Rect scaledExpandedBounds = Rect.fromLTRB(5, 5.5, 10.5, 13);
|
||||
expect(canvas.getLocalClipBounds(), closeToRect(scaledExpandedBounds));
|
||||
// Destination bounds are unaffected by transform
|
||||
expect(canvas.getDestinationClipBounds(), closeToRect(clipExpandedBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
});
|
||||
|
||||
test('Canvas.clipRect(doAA=false) affects canvas.getClipBounds', () async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
canvas.clipRect(clipBounds, doAntiAlias: false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15));
|
||||
// Both clip bounds have changed
|
||||
expect(canvas.getLocalClipBounds(), notCloseToRect(clipBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipBounds));
|
||||
// Previous return values have not changed
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
|
||||
canvas.save();
|
||||
canvas.scale(2, 2);
|
||||
const Rect scaledClipBounds = Rect.fromLTRB(5.1, 5.65, 10.2, 12.85);
|
||||
expect(canvas.getLocalClipBounds(), closeToRect(scaledClipBounds));
|
||||
// Destination bounds are unaffected by transform
|
||||
expect(canvas.getDestinationClipBounds(), closeToRect(clipBounds));
|
||||
canvas.restore();
|
||||
|
||||
@@ -773,21 +812,21 @@ void main() {
|
||||
const Rect clipBounds2 = Rect.fromLTRB(10.0, 10.0, 20.0, 20.0);
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(clipBounds1);
|
||||
canvas.clipRect(clipBounds1, doAntiAlias: false);
|
||||
canvas.translate(0, 10.0);
|
||||
canvas.clipRect(clipBounds1);
|
||||
canvas.clipRect(clipBounds1, doAntiAlias: false);
|
||||
expect(canvas.getDestinationClipBounds().isEmpty, isTrue);
|
||||
canvas.restore();
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(clipBounds1);
|
||||
canvas.clipRect(clipBounds1, doAntiAlias: false);
|
||||
canvas.translate(-10.0, -10.0);
|
||||
canvas.clipRect(clipBounds2);
|
||||
canvas.clipRect(clipBounds2, doAntiAlias: false);
|
||||
expect(canvas.getDestinationClipBounds(), clipBounds1);
|
||||
canvas.restore();
|
||||
});
|
||||
|
||||
test('Canvas.clipRRect affects canvas.getClipBounds', () async {
|
||||
test('Canvas.clipRRect(doAA=true) affects canvas.getClipBounds', () async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
@@ -799,16 +838,16 @@ void main() {
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipExpandedBounds));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15));
|
||||
// Both clip bounds have changed
|
||||
expect(canvas.getLocalClipBounds(), notCloseToRect(clipExpandedBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipExpandedBounds));
|
||||
// Previous return values have not changed
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipExpandedBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
@@ -820,6 +859,46 @@ void main() {
|
||||
const Rect scaledExpandedBounds = Rect.fromLTRB(5, 5.5, 10.5, 13);
|
||||
expect(canvas.getLocalClipBounds(), closeToRect(scaledExpandedBounds));
|
||||
// Destination bounds are unaffected by transform
|
||||
expect(canvas.getDestinationClipBounds(), closeToRect(clipExpandedBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
});
|
||||
|
||||
test('Canvas.clipRRect(doAA=false) affects canvas.getClipBounds', () async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
final RRect clip = RRect.fromRectAndRadius(clipBounds, const Radius.circular(3));
|
||||
canvas.clipRRect(clip, doAntiAlias: false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15), doAntiAlias: false);
|
||||
// Both clip bounds have changed
|
||||
expect(canvas.getLocalClipBounds(), notCloseToRect(clipBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipBounds));
|
||||
// Previous return values have not changed
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
|
||||
canvas.save();
|
||||
canvas.scale(2, 2);
|
||||
const Rect scaledClipBounds = Rect.fromLTRB(5.1, 5.65, 10.2, 12.85);
|
||||
expect(canvas.getLocalClipBounds(), closeToRect(scaledClipBounds));
|
||||
// Destination bounds are unaffected by transform
|
||||
expect(canvas.getDestinationClipBounds(), closeToRect(clipBounds));
|
||||
canvas.restore();
|
||||
|
||||
@@ -837,21 +916,21 @@ void main() {
|
||||
final RRect clip2 = RRect.fromRectAndRadius(clipBounds2, const Radius.circular(3));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRRect(clip1);
|
||||
canvas.clipRRect(clip1, doAntiAlias: false);
|
||||
canvas.translate(0, 10.0);
|
||||
canvas.clipRRect(clip1);
|
||||
canvas.clipRRect(clip1, doAntiAlias: false);
|
||||
expect(canvas.getDestinationClipBounds().isEmpty, isTrue);
|
||||
canvas.restore();
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRRect(clip1);
|
||||
canvas.clipRRect(clip1, doAntiAlias: false);
|
||||
canvas.translate(-10.0, -10.0);
|
||||
canvas.clipRRect(clip2);
|
||||
canvas.clipRRect(clip2, doAntiAlias: false);
|
||||
expect(canvas.getDestinationClipBounds(), clipBounds1);
|
||||
canvas.restore();
|
||||
});
|
||||
|
||||
test('Canvas.clipPath affects canvas.getClipBounds', () async {
|
||||
test('Canvas.clipPath(doAA=true) affects canvas.getClipBounds', () async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
@@ -863,16 +942,16 @@ void main() {
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipExpandedBounds));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15));
|
||||
// Both clip bounds have changed
|
||||
expect(canvas.getLocalClipBounds(), notCloseToRect(clipExpandedBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipExpandedBounds));
|
||||
// Previous return values have not changed
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipExpandedBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
@@ -884,6 +963,46 @@ void main() {
|
||||
const Rect scaledExpandedBounds = Rect.fromLTRB(5, 5.5, 10.5, 13);
|
||||
expect(canvas.getLocalClipBounds(), closeToRect(scaledExpandedBounds));
|
||||
// Destination bounds are unaffected by transform
|
||||
expect(canvas.getDestinationClipBounds(), closeToRect(clipExpandedBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
});
|
||||
|
||||
test('Canvas.clipPath(doAA=false) affects canvas.getClipBounds', () async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
final Path clip = Path()..addRect(clipBounds)..addOval(clipBounds);
|
||||
canvas.clipPath(clip, doAntiAlias: false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15), doAntiAlias: false);
|
||||
// Both clip bounds have changed
|
||||
expect(canvas.getLocalClipBounds(), notCloseToRect(clipBounds));
|
||||
expect(canvas.getDestinationClipBounds(), notCloseToRect(clipBounds));
|
||||
// Previous return values have not changed
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
canvas.restore();
|
||||
|
||||
// save/restore returned the values to their original values
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
|
||||
canvas.save();
|
||||
canvas.scale(2, 2);
|
||||
const Rect scaledClipBounds = Rect.fromLTRB(5.1, 5.65, 10.2, 12.85);
|
||||
expect(canvas.getLocalClipBounds(), closeToRect(scaledClipBounds));
|
||||
// Destination bounds are unaffected by transform
|
||||
expect(canvas.getDestinationClipBounds(), closeToRect(clipBounds));
|
||||
canvas.restore();
|
||||
|
||||
@@ -901,16 +1020,16 @@ void main() {
|
||||
final Path clip2 = Path()..addRect(clipBounds2)..addOval(clipBounds2);
|
||||
|
||||
canvas.save();
|
||||
canvas.clipPath(clip1);
|
||||
canvas.clipPath(clip1, doAntiAlias: false);
|
||||
canvas.translate(0, 10.0);
|
||||
canvas.clipPath(clip1);
|
||||
canvas.clipPath(clip1, doAntiAlias: false);
|
||||
expect(canvas.getDestinationClipBounds().isEmpty, isTrue);
|
||||
canvas.restore();
|
||||
|
||||
canvas.save();
|
||||
canvas.clipPath(clip1);
|
||||
canvas.clipPath(clip1, doAntiAlias: false);
|
||||
canvas.translate(-10.0, -10.0);
|
||||
canvas.clipPath(clip2);
|
||||
canvas.clipPath(clip2, doAntiAlias: false);
|
||||
expect(canvas.getDestinationClipBounds(), clipBounds1);
|
||||
canvas.restore();
|
||||
});
|
||||
@@ -919,16 +1038,15 @@ void main() {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas canvas = Canvas(recorder);
|
||||
const Rect clipBounds = Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
|
||||
const Rect clipExpandedBounds = Rect.fromLTRB(10, 11, 21, 26);
|
||||
canvas.clipRect(clipBounds);
|
||||
canvas.clipRect(clipBounds, doAntiAlias: false);
|
||||
|
||||
// Save initial return values for testing restored values
|
||||
final Rect initialLocalBounds = canvas.getLocalClipBounds();
|
||||
final Rect initialDestinationBounds = canvas.getDestinationClipBounds();
|
||||
expect(initialLocalBounds, closeToRect(clipExpandedBounds));
|
||||
expect(initialLocalBounds, closeToRect(clipBounds));
|
||||
expect(initialDestinationBounds, closeToRect(clipBounds));
|
||||
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15), clipOp: ClipOp.difference);
|
||||
canvas.clipRect(const Rect.fromLTRB(0, 0, 15, 15), clipOp: ClipOp.difference, doAntiAlias: false);
|
||||
expect(canvas.getLocalClipBounds(), initialLocalBounds);
|
||||
expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user