[DisplayList] remove obsolete use of Skia goemetry objects in DL utils (#161553)

Accomplishes the `AccumulationRect and MatrixClipTracker` task in
https://github.com/flutter/flutter/issues/161456

Remove legacy Skia geometry APIs from the DisplayList utils classes
(accumulation rect and matrix/clip state tracker) as well as the small
number of remaining uses of them (mostly from their own unit tests).
This commit is contained in:
Jim Graham 2025-01-14 13:25:42 -08:00 committed by GitHub
parent 1b7cd83b57
commit bce2e22231
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 330 additions and 747 deletions

View File

@ -819,8 +819,8 @@ void DisplayListBuilder::Rotate(DlScalar degrees) {
if (SkScalarMod(degrees, 360.0) != 0.0) {
checkForDeferredSave();
Push<RotateOp>(0, degrees);
global_state().rotate(degrees);
layer_local_state().rotate(degrees);
global_state().rotate(DlDegrees(degrees));
layer_local_state().rotate(DlDegrees(degrees));
}
}
void DisplayListBuilder::Skew(DlScalar sx, DlScalar sy) {
@ -914,7 +914,7 @@ void DisplayListBuilder::TransformReset() {
// became singular while we were accumulating the current layer.
// In either case, we should no longer be accumulating any
// contents so we set the layer tracking transform to a singular one.
layer_local_state().setTransform(SkMatrix::Scale(0.0f, 0.0f));
layer_local_state().setTransform(DlMatrix::MakeScale({0.0f, 0.0f, 0.0f}));
}
global_state().setIdentity();
@ -1050,8 +1050,8 @@ void DisplayListBuilder::ClipPath(const DlPath& path,
return;
}
}
global_state().clipPath(path.GetSkPath(), clip_op, is_aa);
layer_local_state().clipPath(path.GetSkPath(), clip_op, is_aa);
global_state().clipPath(path, clip_op, is_aa);
layer_local_state().clipPath(path, clip_op, is_aa);
if (global_state().is_cull_rect_empty() ||
layer_local_state().is_cull_rect_empty()) {
current_info().is_nop = true;
@ -1488,7 +1488,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
const DlRect& src = tex[i];
xform[i].toQuad(src.GetWidth(), src.GetHeight(), quad);
for (int j = 0; j < 4; j++) {
accumulator.accumulate(quad[j]);
accumulator.accumulate(ToDlPoint(quad[j]));
}
}
if (accumulator.is_empty() ||

View File

@ -6,7 +6,7 @@
namespace flutter {
void AccumulationRect::accumulate(SkScalar x, SkScalar y) {
void AccumulationRect::accumulate(DlScalar x, DlScalar y) {
if (!std::isfinite(x) || !std::isfinite(y)) {
return;
}
@ -28,25 +28,25 @@ void AccumulationRect::accumulate(SkScalar x, SkScalar y) {
}
}
void AccumulationRect::accumulate(SkRect r) {
if (r.isEmpty()) {
void AccumulationRect::accumulate(DlRect r) {
if (r.IsEmpty()) {
return;
}
if (r.fLeft < max_x_ && r.fRight > min_x_ && //
r.fTop < max_y_ && r.fBottom > min_y_) {
if (r.GetLeft() < max_x_ && r.GetRight() > min_x_ && //
r.GetTop() < max_y_ && r.GetBottom() > min_y_) {
record_overlapping_bounds();
}
if (min_x_ > r.fLeft) {
min_x_ = r.fLeft;
if (min_x_ > r.GetLeft()) {
min_x_ = r.GetLeft();
}
if (min_y_ > r.fTop) {
min_y_ = r.fTop;
if (min_y_ > r.GetTop()) {
min_y_ = r.GetTop();
}
if (max_x_ < r.fRight) {
max_x_ = r.fRight;
if (max_x_ < r.GetRight()) {
max_x_ = r.GetRight();
}
if (max_y_ < r.fBottom) {
max_y_ = r.fBottom;
if (max_y_ < r.GetBottom()) {
max_y_ = r.GetBottom();
}
}
@ -78,17 +78,11 @@ DlRect AccumulationRect::GetBounds() const {
: DlRect();
}
SkRect AccumulationRect::bounds() const {
return (max_x_ >= min_x_ && max_y_ >= min_y_)
? SkRect::MakeLTRB(min_x_, min_y_, max_x_, max_y_)
: SkRect::MakeEmpty();
}
void AccumulationRect::reset() {
min_x_ = std::numeric_limits<SkScalar>::infinity();
min_y_ = std::numeric_limits<SkScalar>::infinity();
max_x_ = -std::numeric_limits<SkScalar>::infinity();
max_y_ = -std::numeric_limits<SkScalar>::infinity();
min_x_ = std::numeric_limits<DlScalar>::infinity();
min_y_ = std::numeric_limits<DlScalar>::infinity();
max_x_ = -std::numeric_limits<DlScalar>::infinity();
max_y_ = -std::numeric_limits<DlScalar>::infinity();
overlap_detected_ = false;
}

View File

@ -5,11 +5,7 @@
#ifndef FLUTTER_DISPLAY_LIST_UTILS_DL_ACCUMULATION_RECT_H_
#define FLUTTER_DISPLAY_LIST_UTILS_DL_ACCUMULATION_RECT_H_
#include <functional>
#include "flutter/display_list/geometry/dl_geometry_types.h"
#include "flutter/display_list/geometry/dl_rtree.h"
#include "flutter/fml/logging.h"
namespace flutter {
@ -26,18 +22,15 @@ class AccumulationRect {
public:
AccumulationRect() { reset(); }
void accumulate(SkScalar x, SkScalar y);
void accumulate(SkPoint p) { accumulate(p.fX, p.fY); }
void accumulate(DlScalar x, DlScalar y);
void accumulate(DlPoint p) { accumulate(p.x, p.y); }
void accumulate(SkRect r);
void accumulate(DlRect r) { accumulate(ToSkRect(r)); }
void accumulate(DlRect r);
void accumulate(AccumulationRect& ar);
bool is_empty() const { return min_x_ >= max_x_ || min_y_ >= max_y_; }
bool is_not_empty() const { return min_x_ < max_x_ && min_y_ < max_y_; }
DlRect GetBounds() const;
SkRect bounds() const;
void reset();

View File

@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "flutter/display_list/utils/dl_accumulation_rect.h"
#include "flutter/testing/assertions_skia.h"
#include "gtest/gtest.h"
namespace flutter {
@ -13,7 +12,7 @@ TEST(DisplayListAccumulationRect, Constructor) {
AccumulationRect accumulator;
EXPECT_TRUE(accumulator.is_empty());
EXPECT_TRUE(accumulator.bounds().isEmpty());
EXPECT_TRUE(accumulator.GetBounds().IsEmpty());
EXPECT_FALSE(accumulator.overlap_detected());
}
@ -22,14 +21,14 @@ TEST(DisplayListAccumulationRect, OnePoint) {
accumulator.accumulate(10.0f, 10.0f);
EXPECT_TRUE(accumulator.is_empty());
EXPECT_TRUE(accumulator.bounds().isEmpty());
EXPECT_TRUE(accumulator.GetBounds().IsEmpty());
EXPECT_FALSE(accumulator.overlap_detected());
}
TEST(DisplayListAccumulationRect, TwoPoints) {
auto test = [](DlScalar x1, DlScalar y1, //
DlScalar x2, DlScalar y2, //
SkRect bounds, //
DlRect bounds, //
bool should_be_empty, bool should_overlap,
const std::string& label) {
{
@ -38,19 +37,8 @@ TEST(DisplayListAccumulationRect, TwoPoints) {
accumulator.accumulate(x2, y2);
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
{
AccumulationRect accumulator;
accumulator.accumulate(SkPoint::Make(x1, y1));
accumulator.accumulate(SkPoint::Make(x2, y2));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
@ -60,19 +48,19 @@ TEST(DisplayListAccumulationRect, TwoPoints) {
accumulator.accumulate(DlPoint(x2, y2));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
};
test(10.0f, 10.0f, 10.0f, 10.0f, SkRect::MakeLTRB(10.0f, 10.0f, 10.0f, 10.0f),
test(10.0f, 10.0f, 10.0f, 10.0f, DlRect::MakeLTRB(10.0f, 10.0f, 10.0f, 10.0f),
true, false, "Same");
test(10.0f, 10.0f, 20.0f, 10.0f, SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 10.0f),
test(10.0f, 10.0f, 20.0f, 10.0f, DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 10.0f),
true, false, "Horizontal");
test(10.0f, 10.0f, 10.0f, 20.0f, SkRect::MakeLTRB(10.0f, 10.0f, 10.0f, 20.0f),
test(10.0f, 10.0f, 10.0f, 20.0f, DlRect::MakeLTRB(10.0f, 10.0f, 10.0f, 20.0f),
true, false, "Vertical");
test(10.0f, 10.0f, 20.0f, 20.0f, SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
test(10.0f, 10.0f, 20.0f, 20.0f, DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
false, false, "Diagonal");
}
@ -80,7 +68,7 @@ TEST(DisplayListAccumulationRect, ThreePoints) {
auto test = [](DlScalar x1, DlScalar y1, //
DlScalar x2, DlScalar y2, //
DlScalar x3, DlScalar y3, //
SkRect bounds, //
DlRect bounds, //
bool should_be_empty, bool should_overlap,
const std::string& label) {
{
@ -90,20 +78,8 @@ TEST(DisplayListAccumulationRect, ThreePoints) {
accumulator.accumulate(x3, y3);
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
{
AccumulationRect accumulator;
accumulator.accumulate(SkPoint::Make(x1, y1));
accumulator.accumulate(SkPoint::Make(x2, y2));
accumulator.accumulate(SkPoint::Make(x3, y3));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
@ -114,36 +90,36 @@ TEST(DisplayListAccumulationRect, ThreePoints) {
accumulator.accumulate(DlPoint(x3, y3));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
};
test(10.0f, 10.0f, 10.0f, 10.0f, 10.0f, 10.0f,
SkRect::MakeLTRB(10.0f, 10.0f, 10.0f, 10.0f), true, false, "Same");
DlRect::MakeLTRB(10.0f, 10.0f, 10.0f, 10.0f), true, false, "Same");
test(10.0f, 10.0f, 20.0f, 10.0f, 15.0f, 10.0f,
SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 10.0f), true, false, "Horizontal");
DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 10.0f), true, false, "Horizontal");
test(10.0f, 10.0f, 10.0f, 20.0f, 10.0f, 15.0f,
SkRect::MakeLTRB(10.0f, 10.0f, 10.0f, 20.0f), true, false, "Vertical");
DlRect::MakeLTRB(10.0f, 10.0f, 10.0f, 20.0f), true, false, "Vertical");
test(10.0f, 10.0f, 20.0f, 20.0f, 25.0f, 15.0f,
SkRect::MakeLTRB(10.0f, 10.0f, 25.0f, 20.0f), false, false, "Disjoint");
DlRect::MakeLTRB(10.0f, 10.0f, 25.0f, 20.0f), false, false, "Disjoint");
test(10.0f, 10.0f, 20.0f, 20.0f, 15.0f, 15.0f,
SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), false, true, "Inside");
DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), false, true, "Inside");
}
TEST(DisplayListAccumulationRect, EmptyRect) {
auto test = [](DlScalar l, DlScalar t, DlScalar r, DlScalar b, //
SkRect bounds, //
DlRect bounds, //
bool should_be_empty, bool should_overlap,
const std::string& label) {
{
AccumulationRect accumulator;
accumulator.accumulate(SkRect::MakeLTRB(l, t, r, b));
accumulator.accumulate(DlRect::MakeLTRB(l, t, r, b));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
@ -152,8 +128,8 @@ TEST(DisplayListAccumulationRect, EmptyRect) {
accumulator.accumulate(DlRect::MakeLTRB(l, t, r, b));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
@ -162,12 +138,12 @@ TEST(DisplayListAccumulationRect, EmptyRect) {
content.accumulate(l, t);
content.accumulate(r, b);
EXPECT_EQ(content.is_empty(), should_be_empty) << label;
EXPECT_EQ(content.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(content.GetBounds().IsEmpty(), should_be_empty) << label;
// bounds for an accumulation by points may be different than the
// bounds for an accumulation by the rect they produce because
// construction by points has no "empty rejection" case.
if (!should_be_empty) {
EXPECT_EQ(content.bounds(), bounds) << label;
EXPECT_EQ(content.GetBounds(), bounds) << label;
}
EXPECT_EQ(content.overlap_detected(), should_overlap) << label;
@ -175,47 +151,36 @@ TEST(DisplayListAccumulationRect, EmptyRect) {
accumulator.accumulate(content);
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
};
test(10.0f, 10.0f, 10.0f, 10.0f, SkRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f),
test(10.0f, 10.0f, 10.0f, 10.0f, DlRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f),
true, false, "Singular");
test(10.0f, 10.0f, 20.0f, 10.0f, SkRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f),
test(10.0f, 10.0f, 20.0f, 10.0f, DlRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f),
true, false, "Horizontal Empty");
test(10.0f, 10.0f, 10.0f, 20.0f, SkRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f),
test(10.0f, 10.0f, 10.0f, 20.0f, DlRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f),
true, false, "Vertical Empty");
test(10.0f, 10.0f, 20.0f, 20.0f, SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
test(10.0f, 10.0f, 20.0f, 20.0f, DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
false, false, "Non-Empty");
}
TEST(DisplayListAccumulationRect, TwoRects) {
auto test = [](DlScalar l1, DlScalar t1, DlScalar r1, DlScalar b1, //
DlScalar l2, DlScalar t2, DlScalar r2, DlScalar b2, //
SkRect bounds, //
DlRect bounds, //
bool should_be_empty, bool should_overlap,
const std::string& label) {
{
AccumulationRect accumulator;
accumulator.accumulate(SkRect::MakeLTRB(l1, t1, r1, b1));
accumulator.accumulate(SkRect::MakeLTRB(l2, t2, r2, b2));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
{
AccumulationRect accumulator;
accumulator.accumulate(DlRect::MakeLTRB(l1, t1, r1, b1));
accumulator.accumulate(DlRect::MakeLTRB(l2, t2, r2, b2));
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
@ -233,39 +198,39 @@ TEST(DisplayListAccumulationRect, TwoRects) {
accumulator.accumulate(content2);
EXPECT_EQ(accumulator.is_empty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds().isEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.bounds(), bounds) << label;
EXPECT_EQ(accumulator.GetBounds().IsEmpty(), should_be_empty) << label;
EXPECT_EQ(accumulator.GetBounds(), bounds) << label;
EXPECT_EQ(accumulator.overlap_detected(), should_overlap) << label;
}
};
test(10.0f, 10.0f, 10.0f, 10.0f, //
20.0f, 20.0f, 20.0f, 20.0f, //
SkRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f), //
DlRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f), //
true, false, "Empty + Empty");
test(10.0f, 10.0f, 20.0f, 10.0f, //
10.0f, 10.0f, 10.0f, 20.0f, //
SkRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f), //
DlRect::MakeLTRB(0.0f, 0.0f, 0.0f, 0.0f), //
true, false, "Horizontal + Vertical");
test(10.0f, 10.0f, 10.0f, 10.0f, //
15.0f, 15.0f, 20.0f, 20.0f, //
SkRect::MakeLTRB(15.0f, 15.0f, 20.0f, 20.0f), //
DlRect::MakeLTRB(15.0f, 15.0f, 20.0f, 20.0f), //
false, false, "Empty + Non-Empty");
test(10.0f, 10.0f, 15.0f, 15.0f, //
20.0f, 20.0f, 20.0f, 20.0f, //
SkRect::MakeLTRB(10.0f, 10.0f, 15.0f, 15.0f), //
DlRect::MakeLTRB(10.0f, 10.0f, 15.0f, 15.0f), //
false, false, "Non-Empty + Empty");
test(10.0f, 10.0f, 15.0f, 15.0f, //
15.0f, 15.0f, 20.0f, 20.0f, //
SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), //
DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), //
false, false, "Abutting");
test(10.0f, 10.0f, 15.0f, 15.0f, //
16.0f, 16.0f, 20.0f, 20.0f, //
SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), //
DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), //
false, false, "Disjoint");
test(10.0f, 10.0f, 16.0f, 16.0f, //
15.0f, 15.0f, 20.0f, 20.0f, //
SkRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), //
DlRect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), //
false, true, "Overlapping");
}

View File

@ -9,22 +9,8 @@
namespace flutter {
bool DisplayListMatrixClipState::is_3x3(const SkM44& m) {
// clang-format off
return ( m.rc(0, 2) == 0 &&
m.rc(1, 2) == 0 &&
m.rc(2, 0) == 0 && m.rc(2, 1) == 0 && m.rc(2, 2) == 1 && m.rc(2, 3) == 0 &&
m.rc(3, 2) == 0);
// clang-format on
}
static constexpr DlRect kEmpty = DlRect();
static const DlRect& ProtectEmpty(const SkRect& rect) {
// isEmpty protects us against NaN while we normalize any empty cull rects
return rect.isEmpty() ? kEmpty : ToDlRect(rect);
}
static const DlRect& ProtectEmpty(const DlRect& rect) {
// isEmpty protects us against NaN while we normalize any empty cull rects
return rect.IsEmpty() ? kEmpty : rect;
@ -34,17 +20,6 @@ DisplayListMatrixClipState::DisplayListMatrixClipState(const DlRect& cull_rect,
const DlMatrix& matrix)
: cull_rect_(ProtectEmpty(cull_rect)), matrix_(matrix) {}
DisplayListMatrixClipState::DisplayListMatrixClipState(const SkRect& cull_rect)
: cull_rect_(ProtectEmpty(cull_rect)), matrix_(DlMatrix()) {}
DisplayListMatrixClipState::DisplayListMatrixClipState(const SkRect& cull_rect,
const SkMatrix& matrix)
: cull_rect_(ProtectEmpty(cull_rect)), matrix_(ToDlMatrix(matrix)) {}
DisplayListMatrixClipState::DisplayListMatrixClipState(const SkRect& cull_rect,
const SkM44& matrix)
: cull_rect_(ProtectEmpty(cull_rect)), matrix_(ToDlMatrix(matrix)) {}
bool DisplayListMatrixClipState::inverseTransform(
const DisplayListMatrixClipState& tracker) {
if (tracker.is_matrix_invertable()) {
@ -54,18 +29,6 @@ bool DisplayListMatrixClipState::inverseTransform(
return false;
}
bool DisplayListMatrixClipState::mapAndClipRect(const SkRect& src,
SkRect* mapped) const {
DlRect dl_mapped = ToDlRect(src).TransformAndClipBounds(matrix_);
auto dl_intersected = dl_mapped.Intersection(cull_rect_);
if (dl_intersected.has_value()) {
*mapped = ToSkRect(dl_intersected.value());
return true;
}
mapped->setEmpty();
return false;
}
bool DisplayListMatrixClipState::mapAndClipRect(const DlRect& src,
DlRect* mapped) const {
DlRect dl_mapped = src.TransformAndClipBounds(matrix_);

View File

@ -11,13 +11,6 @@
#include "flutter/display_list/geometry/dl_geometry_types.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkM44.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkScalar.h"
namespace flutter {
class DisplayListMatrixClipState {
@ -27,13 +20,8 @@ class DisplayListMatrixClipState {
public:
explicit DisplayListMatrixClipState(const DlRect& cull_rect,
const DlMatrix& matrix = DlMatrix());
explicit DisplayListMatrixClipState(const SkRect& cull_rect);
DisplayListMatrixClipState(const SkRect& cull_rect, const SkMatrix& matrix);
DisplayListMatrixClipState(const SkRect& cull_rect, const SkM44& matrix);
DisplayListMatrixClipState(const DisplayListMatrixClipState& other) = default;
static bool is_3x3(const SkM44& m44);
// This method should almost never be used as it breaks the encapsulation
// of the enclosing clips. However it is needed for practical purposes in
// some rare cases - such as when a saveLayer is collecting rendering
@ -44,65 +32,41 @@ class DisplayListMatrixClipState {
// Omitting the |cull_rect| argument, or passing nullptr, will restore the
// cull rect to the initial value it had when the tracker was constructed.
void resetDeviceCullRect(const DlRect& cull_rect);
void resetDeviceCullRect(const SkRect& cull_rect) {
resetDeviceCullRect(ToDlRect(cull_rect));
}
void resetLocalCullRect(const DlRect& cull_rect);
void resetLocalCullRect(const SkRect& cull_rect) {
resetLocalCullRect(ToDlRect(cull_rect));
}
bool using_4x4_matrix() const { return !matrix_.IsAffine(); }
bool is_matrix_invertable() const { return matrix_.IsInvertible(); }
bool has_perspective() const { return matrix_.HasPerspective(); }
const DlMatrix& matrix() const { return matrix_; }
SkM44 matrix_4x4() const { return SkM44::ColMajor(matrix_.m); }
SkMatrix matrix_3x3() const { return ToSkMatrix(matrix_); }
SkRect local_cull_rect() const { return ToSkRect(GetLocalCullCoverage()); }
DlRect GetLocalCullCoverage() const;
SkRect device_cull_rect() const { return ToSkRect(cull_rect_); }
DlRect GetDeviceCullCoverage() const { return cull_rect_; }
bool rect_covers_cull(const DlRect& content) const;
bool rect_covers_cull(const SkRect& content) const {
return rect_covers_cull(ToDlRect(content));
}
bool oval_covers_cull(const DlRect& content_bounds) const;
bool oval_covers_cull(const SkRect& content_bounds) const {
return oval_covers_cull(ToDlRect(content_bounds));
}
bool rrect_covers_cull(const DlRoundRect& content) const;
bool rrect_covers_cull(const SkRRect& content) const {
return rrect_covers_cull(ToDlRoundRect(content));
}
bool content_culled(const DlRect& content_bounds) const;
bool content_culled(const SkRect& content_bounds) const {
return content_culled(ToDlRect(content_bounds));
}
bool is_cull_rect_empty() const { return cull_rect_.IsEmpty(); }
void translate(SkScalar tx, SkScalar ty) {
void translate(DlScalar tx, DlScalar ty) {
matrix_ = matrix_.Translate({tx, ty});
}
void scale(SkScalar sx, SkScalar sy) {
void scale(DlScalar sx, DlScalar sy) {
matrix_ = matrix_.Scale({sx, sy, 1.0f});
}
void skew(SkScalar skx, SkScalar sky) {
void skew(DlScalar skx, DlScalar sky) {
matrix_ = matrix_ * DlMatrix::MakeSkew(skx, sky);
}
void rotate(SkScalar degrees) {
matrix_ = matrix_ * DlMatrix::MakeRotationZ(DlDegrees(degrees));
void rotate(DlRadians angle) {
matrix_ = matrix_ * DlMatrix::MakeRotationZ(angle);
}
void transform(const DlMatrix& matrix) { matrix_ = matrix_ * matrix; }
void transform(const SkM44& m44) { transform(ToDlMatrix(m44)); }
void transform(const SkMatrix& matrix) { transform(ToDlMatrix(matrix)); }
// clang-format off
void transform2DAffine(
SkScalar mxx, SkScalar mxy, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myt) {
DlScalar mxx, DlScalar mxy, DlScalar mxt,
DlScalar myx, DlScalar myy, DlScalar myt) {
matrix_ = matrix_ * DlMatrix::MakeColumn(
mxx, myx, 0.0f, 0.0f,
mxy, myy, 0.0f, 0.0f,
@ -111,10 +75,10 @@ class DisplayListMatrixClipState {
);
}
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) {
DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
matrix_ = matrix_ * DlMatrix::MakeColumn(
mxx, myx, mzx, mwx,
mxy, myy, mzy, mwy,
@ -124,8 +88,6 @@ class DisplayListMatrixClipState {
}
// clang-format on
void setTransform(const DlMatrix& matrix) { matrix_ = matrix; }
void setTransform(const SkMatrix& matrix) { matrix_ = ToDlMatrix(matrix); }
void setTransform(const SkM44& m44) { matrix_ = ToDlMatrix(m44); }
void setIdentity() { matrix_ = DlMatrix(); }
// If the matrix in |other_tracker| is invertible then transform this
// tracker by the inverse of its matrix and return true. Otherwise,
@ -137,38 +99,17 @@ class DisplayListMatrixClipState {
*mapped = src.TransformAndClipBounds(matrix_);
return matrix_.IsAligned2D();
}
bool mapRect(SkRect* rect) const { return mapRect(*rect, rect); }
bool mapRect(const SkRect& src, SkRect* mapped) const {
*mapped = ToSkRect(ToDlRect(src).TransformAndClipBounds(matrix_));
return matrix_.IsAligned2D();
}
/// @brief Maps the rect by the current matrix and then clips it against
/// the current cull rect, returning true if the result is non-empty.
bool mapAndClipRect(SkRect* rect) const {
return mapAndClipRect(*rect, rect);
}
bool mapAndClipRect(const SkRect& src, SkRect* mapped) const;
bool mapAndClipRect(DlRect* rect) const {
return mapAndClipRect(*rect, rect);
}
bool mapAndClipRect(const DlRect& src, DlRect* mapped) const;
void clipRect(const DlRect& rect, ClipOp op, bool is_aa);
void clipRect(const SkRect& rect, ClipOp op, bool is_aa) {
clipRect(ToDlRect(rect), op, is_aa);
}
void clipOval(const DlRect& bounds, ClipOp op, bool is_aa);
void clipOval(const SkRect& bounds, ClipOp op, bool is_aa) {
clipRect(ToDlRect(bounds), op, is_aa);
}
void clipRRect(const DlRoundRect& rrect, ClipOp op, bool is_aa);
void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) {
clipRRect(ToDlRoundRect(rrect), op, is_aa);
}
void clipPath(const SkPath& path, ClipOp op, bool is_aa) {
clipPath(DlPath(path), op, is_aa);
}
void clipPath(const DlPath& path, ClipOp op, bool is_aa);
private:

View File

@ -144,7 +144,7 @@ DlRect DiffContext::MapRect(const DlRect& rect) {
bool DiffContext::PushCullRect(const DlRect& clip) {
state_.matrix_clip.clipRect(clip, DlCanvas::ClipOp::kIntersect, false);
return !state_.matrix_clip.device_cull_rect().isEmpty();
return !state_.matrix_clip.is_cull_rect_empty();
}
const DlMatrix& DiffContext::GetMatrix() const {