Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
flutter::testing::CanvasCompareTester Class Reference

Public Types

enum class  DirectoryStatus {
  kExisted ,
  kCreated ,
  kFailed
}
 

Static Public Member Functions

static void EnableSaveImagesOnFailures ()
 
static void PrintFailureImageFileNames ()
 
static void RenderAll (const std::unique_ptr< DlSurfaceProvider > &provider, const TestParameters &params, const BoundsTolerance &tolerance=DefaultTolerance)
 
static void RenderWithSaveRestore (const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
 
static void RenderWithAttributes (const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
 
static void RenderWithStrokes (const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance_in)
 
static void RenderWithTransforms (const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
 
static void RenderWithClips (const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &diff_tolerance)
 
static DirectoryStatus CheckDir (const std::string &dir)
 
static void SetupFailureImageDirectory ()
 
static void save_to_png (const RenderResult &result, const std::string &op_desc, const std::string &reason)
 
static void RenderWith (const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance_in, const CaseParameters &caseP)
 
static bool fuzzyCompare (uint32_t pixel_a, uint32_t pixel_b, int fudge)
 
static int groupOpacityFudgeFactor (const RenderEnvironment &env)
 
static void checkGroupOpacity (const RenderEnvironment &env, const sk_sp< DisplayList > &display_list, const RenderResult &ref_result, const std::string &info, DlColor bg)
 
static bool checkPixels (const RenderResult &ref_result, const DlRect ref_bounds, const std::string &info, const DlColor bg=DlColor::kTransparent())
 
static int countModifiedTransparentPixels (const RenderResult &ref_result, const RenderResult &test_result)
 
static bool quickCompareToReference (const RenderResult &ref_result, const RenderResult &test_result, bool should_match, const std::string &info)
 
static void compareToReference (const RenderResult &test_result, const RenderResult &ref_result, const std::string &info, const DlRect *bounds, const BoundsTolerance *tolerance, const DlColor bg, bool fuzzyCompares=false, uint32_t width=kTestWidth, uint32_t height=kTestHeight, bool printMismatches=false)
 
static void showBoundsOverflow (const std::string &info, DlIRect &bounds, const BoundsTolerance *tolerance, int pixLeft, int pixTop, int pixRight, int pixBottom)
 

Static Public Attributes

static BoundsTolerance DefaultTolerance
 

Detailed Description

Definition at line 908 of file dl_rendering_unittests.cc.

Member Enumeration Documentation

◆ DirectoryStatus

Member Function Documentation

◆ CheckDir()

static DirectoryStatus flutter::testing::CanvasCompareTester::CheckDir ( const std::string &  dir)
inlinestatic

Definition at line 1810 of file dl_rendering_unittests.cc.

1810 {
1811 fml::UniqueFD ret =
1813 if (ret.is_valid()) {
1815 }
1816 ret =
1818 if (ret.is_valid()) {
1820 }
1821 FML_LOG(ERROR) << "Could not create directory (" << dir
1822 << ") for impeller failure images" << ", ret = " << ret.get()
1823 << ", errno = " << errno;
1825 }
bool is_valid() const
const T & get() const
#define FML_LOG(severity)
Definition logging.h:101
fml::UniqueFD OpenDirectory(const char *path, bool create_if_necessary, FilePermission permission)
Definition file_posix.cc:97

References FML_LOG, fml::UniqueObject< T, Traits >::get(), fml::UniqueObject< T, Traits >::is_valid(), kCreated, kExisted, kFailed, fml::kRead, fml::kReadWrite, and fml::OpenDirectory().

Referenced by SetupFailureImageDirectory().

◆ checkGroupOpacity()

static void flutter::testing::CanvasCompareTester::checkGroupOpacity ( const RenderEnvironment env,
const sk_sp< DisplayList > &  display_list,
const RenderResult ref_result,
const std::string &  info,
DlColor  bg 
)
inlinestatic

Definition at line 2004 of file dl_rendering_unittests.cc.

2008 {
2009 DlScalar opacity = 128.0 / 255.0;
2010
2011 if (opacity > 0) {
2012 return;
2013 }
2014 DisplayListJobRenderer opacity_job(display_list);
2015 RenderJobInfo opacity_info = {
2016 .bg = bg,
2017 .opacity = opacity,
2018 };
2019 RenderResult group_opacity_result =
2020 env.GetResult(opacity_info, opacity_job);
2021
2022 ASSERT_EQ(group_opacity_result.pixel_data->width(), kTestWidth) << info;
2023 ASSERT_EQ(group_opacity_result.pixel_data->height(), kTestHeight) << info;
2024
2025 ASSERT_EQ(ref_result.pixel_data->width(), kTestWidth) << info;
2026 ASSERT_EQ(ref_result.pixel_data->height(), kTestHeight) << info;
2027
2028 int pixels_touched = 0;
2029 int pixels_different = 0;
2030 int max_diff = 0;
2031 // We need to allow some slight differences per component due to the
2032 // fact that rearranging discrete calculations can compound round off
2033 // errors. Off-by-2 is enough for 8 bit components, but for the 565
2034 // tests we allow at least 9 which is the maximum distance between
2035 // samples when converted to 8 bits. (You might think it would be a
2036 // max step of 8 converting 5 bits to 8 bits, but it is really
2037 // converting 31 steps to 255 steps with an average step size of
2038 // 8.23 - 24 of the steps are by 8, but 7 of them are by 9.)
2039 int fudge = groupOpacityFudgeFactor(env);
2040 for (uint32_t y = 0; y < kTestHeight; y++) {
2041 const uint32_t* ref_row = ref_result.pixel_data->addr32(0, y);
2042 const uint32_t* test_row = group_opacity_result.pixel_data->addr32(0, y);
2043 for (uint32_t x = 0; x < kTestWidth; x++) {
2044 uint32_t ref_pixel = ref_row[x];
2045 uint32_t test_pixel = test_row[x];
2046 if (ref_pixel != bg.argb() || test_pixel != bg.argb()) {
2047 pixels_touched++;
2048 for (int i = 0; i < 32; i += 8) {
2049 int ref_comp = (ref_pixel >> i) & 0xff;
2050 int bg_comp = (bg.argb() >> i) & 0xff;
2051 DlScalar faded_comp = bg_comp + (ref_comp - bg_comp) * opacity;
2052 int test_comp = (test_pixel >> i) & 0xff;
2053 if (std::abs(faded_comp - test_comp) > fudge) {
2054 int diff = std::abs(faded_comp - test_comp);
2055 if (max_diff < diff) {
2056 max_diff = diff;
2057 }
2058 pixels_different++;
2059 break;
2060 }
2061 }
2062 }
2063 }
2064 }
2065 ASSERT_GT(pixels_touched, 20) << info;
2066 if (pixels_different > 1) {
2067 FML_LOG(ERROR) << "max diff == " << max_diff << " for " << info;
2068 }
2069 ASSERT_LE(pixels_different, 1) << info;
2070 }
static int groupOpacityFudgeFactor(const RenderEnvironment &env)
int32_t x
double y
constexpr uint32_t kTestWidth
constexpr uint32_t kTestHeight
impeller::Scalar DlScalar

References flutter::DlColor::argb(), flutter::testing::RenderJobInfo::bg, FML_LOG, flutter::testing::RenderEnvironment::GetResult(), groupOpacityFudgeFactor(), i, flutter::testing::kTestHeight, flutter::testing::kTestWidth, flutter::testing::RenderResult::pixel_data, x, and y.

Referenced by RenderWith().

◆ checkPixels()

static bool flutter::testing::CanvasCompareTester::checkPixels ( const RenderResult ref_result,
const DlRect  ref_bounds,
const std::string &  info,
const DlColor  bg = DlColor::kTransparent() 
)
inlinestatic

Definition at line 2072 of file dl_rendering_unittests.cc.

2075 {
2076 uint32_t untouched = PremultipliedArgb(bg);
2077 int pixels_touched = 0;
2078 int pixels_oob = 0;
2079 DlIRect i_bounds = DlIRect::RoundOut(ref_bounds);
2080 EXPECT_EQ(ref_result.pixel_data->width(), kTestWidth) << info;
2081 EXPECT_EQ(ref_result.pixel_data->height(), kTestWidth) << info;
2082 for (uint32_t y = 0; y < kTestHeight; y++) {
2083 const uint32_t* ref_row = ref_result.pixel_data->addr32(0, y);
2084 for (uint32_t x = 0; x < kTestWidth; x++) {
2085 if (ref_row[x] != untouched) {
2086 pixels_touched++;
2087 if (!i_bounds.Contains(DlIPoint(x, y))) {
2088 pixels_oob++;
2089 }
2090 }
2091 }
2092 }
2093 EXPECT_EQ(pixels_oob, 0) << info;
2094 EXPECT_GT(pixels_touched, 0) << info;
2095 return pixels_oob == 0 && pixels_touched > 0;
2096 }
impeller::IRect32 DlIRect
impeller::IPoint32 DlIPoint
RoundOut(const TRect< U > &r)
Definition rect.h:713

References impeller::TRect< T >::Contains(), flutter::testing::kTestHeight, flutter::testing::kTestWidth, flutter::testing::RenderResult::pixel_data, impeller::TRect< T >::RoundOut(), x, and y.

Referenced by RenderWith().

◆ compareToReference()

static void flutter::testing::CanvasCompareTester::compareToReference ( const RenderResult test_result,
const RenderResult ref_result,
const std::string &  info,
const DlRect bounds,
const BoundsTolerance tolerance,
const DlColor  bg,
bool  fuzzyCompares = false,
uint32_t  width = kTestWidth,
uint32_t  height = kTestHeight,
bool  printMismatches = false 
)
inlinestatic

Definition at line 2145 of file dl_rendering_unittests.cc.

2154 {
2155 uint32_t untouched = PremultipliedArgb(bg);
2156 ASSERT_EQ(test_result.pixel_data->width(), width) << info;
2157 ASSERT_EQ(test_result.pixel_data->height(), height) << info;
2158 DlIRect i_bounds =
2159 bounds ? DlIRect::RoundOut(*bounds) : DlIRect::MakeWH(width, height);
2160
2161 int pixels_different = 0;
2162 int pixels_oob = 0;
2163 uint32_t min_x = width;
2164 uint32_t min_y = height;
2165 uint32_t max_x = 0;
2166 uint32_t max_y = 0;
2167 for (uint32_t y = 0; y < height; y++) {
2168 const uint32_t* ref_row = ref_result.pixel_data->addr32(0, y);
2169 const uint32_t* test_row = test_result.pixel_data->addr32(0, y);
2170 for (uint32_t x = 0; x < width; x++) {
2171 if (bounds && test_row[x] != untouched) {
2172 if (min_x > x) {
2173 min_x = x;
2174 }
2175 if (min_y > y) {
2176 min_y = y;
2177 }
2178 if (max_x <= x) {
2179 max_x = x + 1;
2180 }
2181 if (max_y <= y) {
2182 max_y = y + 1;
2183 }
2184 if (!i_bounds.Contains(DlIPoint(x, y))) {
2185 pixels_oob++;
2186 }
2187 }
2188 bool match = fuzzyCompares ? fuzzyCompare(test_row[x], ref_row[x], 1)
2189 : test_row[x] == ref_row[x];
2190 if (!match) {
2191 if (printMismatches && pixels_different < 5) {
2192 FML_LOG(ERROR) << "pix[" << x << ", " << y
2193 << "] mismatch: " << std::hex << test_row[x]
2194 << "(test) != (ref)" << ref_row[x] << std::dec;
2195 }
2196 pixels_different++;
2197 }
2198 }
2199 }
2200 if (pixels_oob > 0) {
2201 FML_LOG(ERROR) << "pix bounds["
2202 << DlIRect::MakeLTRB(min_x, min_y, max_x, max_y) //
2203 << "]";
2204 FML_LOG(ERROR) << "dl_bounds[" << bounds << "]";
2205 } else if (bounds) {
2206 showBoundsOverflow(info, i_bounds, tolerance, min_x, min_y, max_x, max_y);
2207 }
2208 ASSERT_EQ(pixels_oob, 0) << info;
2209 ASSERT_EQ(pixels_different, 0) << info;
2210 }
static void showBoundsOverflow(const std::string &info, DlIRect &bounds, const BoundsTolerance *tolerance, int pixLeft, int pixTop, int pixRight, int pixBottom)
static bool fuzzyCompare(uint32_t pixel_a, uint32_t pixel_b, int fudge)
int32_t height
int32_t width
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129

References impeller::TRect< T >::Contains(), FML_LOG, fuzzyCompare(), height, impeller::TRect< T >::MakeLTRB(), impeller::TRect< T >::MakeWH(), flutter::testing::RenderResult::pixel_data, impeller::TRect< T >::RoundOut(), showBoundsOverflow(), width, x, and y.

Referenced by flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ countModifiedTransparentPixels()

static int flutter::testing::CanvasCompareTester::countModifiedTransparentPixels ( const RenderResult ref_result,
const RenderResult test_result 
)
inlinestatic

Definition at line 2098 of file dl_rendering_unittests.cc.

2099 {
2100 int count = 0;
2101 for (uint32_t y = 0; y < kTestHeight; y++) {
2102 const uint32_t* ref_row = ref_result.pixel_data->addr32(0, y);
2103 const uint32_t* test_row = test_result.pixel_data->addr32(0, y);
2104 for (uint32_t x = 0; x < kTestWidth; x++) {
2105 if (ref_row[x] != test_row[x]) {
2106 if (ref_row[x] == 0) {
2107 count++;
2108 }
2109 }
2110 }
2111 }
2112 return count;
2113 }

References flutter::testing::kTestHeight, flutter::testing::kTestWidth, flutter::testing::RenderResult::pixel_data, x, and y.

Referenced by flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ EnableSaveImagesOnFailures()

static void flutter::testing::CanvasCompareTester::EnableSaveImagesOnFailures ( )
inlinestatic

Definition at line 915 of file dl_rendering_unittests.cc.

915{ save_failure_images_ = true; }

Referenced by flutter::testing::DisplayListRendering::SetUpTestSuite().

◆ fuzzyCompare()

static bool flutter::testing::CanvasCompareTester::fuzzyCompare ( uint32_t  pixel_a,
uint32_t  pixel_b,
int  fudge 
)
inlinestatic

Definition at line 1981 of file dl_rendering_unittests.cc.

1981 {
1982 for (int i = 0; i < 32; i += 8) {
1983 int comp_a = (pixel_a >> i) & 0xff;
1984 int comp_b = (pixel_b >> i) & 0xff;
1985 if (std::abs(comp_a - comp_b) > fudge) {
1986 return false;
1987 }
1988 }
1989 return true;
1990 }

References i.

Referenced by compareToReference().

◆ groupOpacityFudgeFactor()

static int flutter::testing::CanvasCompareTester::groupOpacityFudgeFactor ( const RenderEnvironment env)
inlinestatic

Definition at line 1992 of file dl_rendering_unittests.cc.

1992 {
1993 if (env.GetPixelFormat() == PixelFormat::k565) {
1994 return 9;
1995 }
1996 if (env.GetProvider()->GetBackendType() == BackendType::kSkiaOpenGL) {
1997 // OpenGL gets a little fuzzy at times. Still, "within 5" (aka +/-4)
1998 // for byte samples is not bad, though the other backends give +/-1
1999 return 5;
2000 }
2001 return 2;
2002 }

References flutter::testing::DlSurfaceProvider::GetBackendType(), flutter::testing::RenderEnvironment::GetPixelFormat(), and flutter::testing::RenderEnvironment::GetProvider().

Referenced by checkGroupOpacity().

◆ PrintFailureImageFileNames()

static void flutter::testing::CanvasCompareTester::PrintFailureImageFileNames ( )
inlinestatic

Definition at line 917 of file dl_rendering_unittests.cc.

917 {
918 if (failure_image_filenames_.empty()) {
919 return;
920 }
921 FML_LOG(INFO);
922 FML_LOG(INFO) << failure_image_filenames_.size() << " images saved in "
923 << failure_image_directory_;
924 for (const std::string& filename : failure_image_filenames_) {
925 FML_LOG(INFO) << " " << filename;
926 }
927 FML_LOG(INFO);
928 }

References FML_LOG.

Referenced by flutter::testing::DisplayListRendering::TearDownTestSuite().

◆ quickCompareToReference()

static bool flutter::testing::CanvasCompareTester::quickCompareToReference ( const RenderResult ref_result,
const RenderResult test_result,
bool  should_match,
const std::string &  info 
)
inlinestatic

Definition at line 2115 of file dl_rendering_unittests.cc.

2118 {
2119 uint32_t w = test_result.pixel_data->width();
2120 uint32_t h = test_result.pixel_data->height();
2121 EXPECT_EQ(w, ref_result.pixel_data->width()) << info;
2122 EXPECT_EQ(h, ref_result.pixel_data->height()) << info;
2123 int pixels_different = 0;
2124 for (uint32_t y = 0; y < h; y++) {
2125 const uint32_t* ref_row = ref_result.pixel_data->addr32(0, y);
2126 const uint32_t* test_row = test_result.pixel_data->addr32(0, y);
2127 for (uint32_t x = 0; x < w; x++) {
2128 if (ref_row[x] != test_row[x]) {
2129 if (should_match && pixels_different < 5) {
2130 FML_LOG(ERROR) << std::hex << ref_row[x] << " != " << test_row[x];
2131 }
2132 pixels_different++;
2133 }
2134 }
2135 }
2136 if (should_match) {
2137 EXPECT_EQ(pixels_different, 0) << info;
2138 return pixels_different == 0;
2139 } else {
2140 EXPECT_NE(pixels_different, 0) << info;
2141 return pixels_different != 0;
2142 }
2143 }
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder h
Definition switch_defs.h:54

References FML_LOG, flutter::h, flutter::testing::RenderResult::pixel_data, x, and y.

Referenced by RenderWith(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ RenderAll()

static void flutter::testing::CanvasCompareTester::RenderAll ( const std::unique_ptr< DlSurfaceProvider > &  provider,
const TestParameters params,
const BoundsTolerance tolerance = DefaultTolerance 
)
inlinestatic

Definition at line 932 of file dl_rendering_unittests.cc.

934 {
935 RenderEnvironment env = RenderEnvironment::MakeN32(provider.get());
936 env.InitializeReference(kEmptyDlSetup, params.dl_renderer());
937
938 RenderWithTransforms(params, env, tolerance);
939 RenderWithClips(params, env, tolerance);
940 RenderWithSaveRestore(params, env, tolerance);
941 // Only test attributes if the canvas version uses the paint object
942 if (params.uses_paint()) {
943 RenderWithAttributes(params, env, tolerance);
944 }
945 }
static void RenderWithAttributes(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
static void RenderWithSaveRestore(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
static void RenderWithClips(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &diff_tolerance)
static void RenderWithTransforms(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
static RenderEnvironment MakeN32(const DlSurfaceProvider *provider)
const EmbeddedViewParams * params
static const DlSetup kEmptyDlSetup

References flutter::testing::RenderEnvironment::InitializeReference(), flutter::testing::kEmptyDlSetup, flutter::testing::RenderEnvironment::MakeN32(), params, RenderWithAttributes(), RenderWithClips(), RenderWithSaveRestore(), and RenderWithTransforms().

Referenced by flutter::testing::DisplayListRendering::RenderAll().

◆ RenderWith()

static void flutter::testing::CanvasCompareTester::RenderWith ( const TestParameters testP,
const RenderEnvironment env,
const BoundsTolerance tolerance_in,
const CaseParameters caseP 
)
inlinestatic

Run a suite of tests on the indicated parameters to determine if the output matches various expectations, including:

  • The rendering does not exceed the bounds computed by the DisplayList into which the operation was recorded.
  • If the parameters indicate an attribute (color, filter, stroke) or and environmental condition (clip, transform, save layer) which should affect the rendering, that it does affect the rendering, and conversely that it does not if it should not.

testP - The parameters of the basic rendering operation being tested such as DrawRect, DrawPath, DrawText, etc. env - The parameters of the test environment for this suite of tests such as the Surface Provider that determines which backend is being used. tolerance_in - A first approximation of how tight the bounds might be for the indicated test and case parameters. Some issues that might require a higher bounds tolerance would include the fact that text glyphs do not consume most of their measured bounds, or that antialiasing is enabled which allows pixels outside the theoretical bounds of the operation's geometry to be rendered. caseP - The parameters under which the test is being rendered, which includes information such as transform, clip, and attributes.

Definition at line 1900 of file dl_rendering_unittests.cc.

1903 {
1904 std::string test_name =
1905 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1906 const std::string info =
1907 env.GetBackendName() + ": " + test_name + " (" + caseP.info() + ")";
1908 const DlColor bg = caseP.bg();
1909 RenderJobInfo base_info = {
1910 .bg = bg,
1911 };
1912
1913 // This is the basic rendering of the specified job. We combine the
1914 // rendering from the test, with the attribute and environment mutations
1915 // from the case
1916 DlJobRenderer dl_job(caseP.dl_setup(), //
1917 testP.dl_renderer(), //
1918 caseP.dl_restore());
1919 RenderResult dl_result = env.GetResult(base_info, dl_job);
1920
1921 ASSERT_EQ(dl_result.pixel_data->width(), kTestWidth) << info;
1922 ASSERT_EQ(dl_result.pixel_data->height(), kTestHeight) << info;
1923
1924 // We construct a display list from the rendering operations which will
1925 // estimate the bounds we expect from the operation, among other properties.
1926 const sk_sp<DisplayList> display_list =
1927 dl_job.MakeDisplayList(env, base_info);
1928
1929 // We now test the result of rendering the operations to verify that:
1930 // - it did render something (pixels touched > 0)
1931 // - no pixels were rendered outside the computed bounds (pixels_oob == 0)
1932 DlRect dl_bounds = display_list->GetBounds();
1933 bool success = checkPixels(dl_result, dl_bounds,
1934 info + " (DisplayList reference)", bg);
1935
1936 // Now we test if the operation should have rendered something different
1937 // compared to the default reference rendering that has no attributes
1938 // applied. Some operations ignore some attributes and so we need to
1939 // examine the test case properties to see if the rendering should or
1940 // should not match the default reference rendering.
1941 //
1942 // quickCompareToReference does both jobs (matches or does not match)
1943 // and we provide it with a boolean indicating if we expect the two
1944 // results to match and a string that prints out the expectation that
1945 // was violated.
1946 if (testP.should_match(env, caseP, dl_job.GetSetupPaint(), dl_job)) {
1947 success = quickCompareToReference(
1948 env.GetReferenceResult(), dl_result, true,
1949 info + " (attribute should not have effect)") &&
1950 success;
1951 } else {
1952 success = quickCompareToReference(
1953 env.GetReferenceResult(), dl_result, false,
1954 info + " (attribute should affect rendering)") &&
1955 success;
1956 }
1957
1958 if (save_failure_images_ && !success) {
1959 FML_LOG(ERROR) << "Rendering issue encountered for: " << *display_list;
1960 save_to_png(dl_result, info + " (Test Result)", "output saved in");
1961 save_to_png(env.GetReferenceResult(), info + " (Test Reference)",
1962 "compare to reference without attributes");
1963 }
1964
1965 // We now determine if the display list is compatible with distributing
1966 // a group opacity to its individual rendering operations. If the
1967 // display list believes that can be done, we double check by asking
1968 // the canvas to render the display list with a group opacity value
1969 // and then see if the results really match a faded version of the
1970 // original rendering results.
1971 //
1972 // If the display list does not promise that it can apply group opacity
1973 // then we do not verify that condition, we allow it the freedom to
1974 // answer "false" conservatively.
1975 if (display_list->can_apply_group_opacity()) {
1976 checkGroupOpacity(env, display_list, dl_result,
1977 info + " with Group Opacity", bg);
1978 }
1979 }
static void checkGroupOpacity(const RenderEnvironment &env, const sk_sp< DisplayList > &display_list, const RenderResult &ref_result, const std::string &info, DlColor bg)
static bool checkPixels(const RenderResult &ref_result, const DlRect ref_bounds, const std::string &info, const DlColor bg=DlColor::kTransparent())
static void save_to_png(const RenderResult &result, const std::string &op_desc, const std::string &reason)
static bool quickCompareToReference(const RenderResult &ref_result, const RenderResult &test_result, bool should_match, const std::string &info)
impeller::Rect DlRect
flutter::DlColor DlColor

References flutter::testing::RenderJobInfo::bg, flutter::testing::CaseParameters::bg(), checkGroupOpacity(), checkPixels(), flutter::testing::TestParameters::dl_renderer(), flutter::testing::CaseParameters::dl_restore(), flutter::testing::CaseParameters::dl_setup(), FML_LOG, flutter::testing::RenderEnvironment::GetBackendName(), flutter::testing::RenderEnvironment::GetReferenceResult(), flutter::testing::RenderEnvironment::GetResult(), flutter::testing::DlJobRenderer::GetSetupPaint(), flutter::testing::CaseParameters::info(), flutter::testing::kTestHeight, flutter::testing::kTestWidth, flutter::testing::DlJobRenderer::MakeDisplayList(), flutter::testing::RenderResult::pixel_data, quickCompareToReference(), save_to_png(), and flutter::testing::TestParameters::should_match().

Referenced by RenderWithAttributes(), RenderWithClips(), RenderWithSaveRestore(), RenderWithStrokes(), RenderWithTransforms(), and flutter::testing::TEST_F().

◆ RenderWithAttributes()

static void flutter::testing::CanvasCompareTester::RenderWithAttributes ( const TestParameters testP,
const RenderEnvironment env,
const BoundsTolerance tolerance 
)
inlinestatic

Definition at line 1171 of file dl_rendering_unittests.cc.

1173 {
1174 RenderWith(testP, env, tolerance, CaseParameters("Defaults Test"));
1175
1176 {
1177 // CPU renderer with default line width of 0 does not show antialiasing
1178 // for stroked primitives, so we make a new reference with a non-trivial
1179 // stroke width to demonstrate the differences
1180 RenderEnvironment aa_env = RenderEnvironment::MakeN32(env.GetProvider());
1181 // Tweak the bounds tolerance for the displacement of 1/10 of a pixel
1182 const BoundsTolerance aa_tolerance = tolerance.addBoundsPadding(1, 1);
1183 auto dl_aa_setup = [=](DlSetupContext ctx, bool is_aa) -> void {
1184 ctx.canvas->Translate(0.1, 0.1);
1185 ctx.paint.setAntiAlias(is_aa);
1186 ctx.paint.setStrokeWidth(5.0);
1187 };
1188 aa_env.InitializeReference(
1189 [=](const DlSetupContext& ctx) { dl_aa_setup(ctx, false); },
1190 testP.dl_renderer());
1191
1192 // clang-format off
1193 // The following section gets re-formatted on every commit even if it
1194 // doesn't change.
1195 RenderWith(
1196 testP, aa_env, aa_tolerance,
1197 CaseParameters(
1198 "AntiAlias == True",
1199 [=](const DlSetupContext& ctx) { dl_aa_setup(ctx, true); }));
1200 RenderWith(
1201 testP, aa_env, aa_tolerance,
1202 CaseParameters(
1203 "AntiAlias == False",
1204 [=](const DlSetupContext& ctx) { dl_aa_setup(ctx, false); }));
1205 // clang-format on
1206 }
1207
1208 // clang-format off
1209 // The following section gets re-formatted on every commit even if it
1210 // doesn't change.
1211 RenderWith( //
1212 testP, env, tolerance,
1213 CaseParameters(
1214 "Color == Blue",
1215 [=](const DlSetupContext& ctx) {
1216 ctx.paint.setColor(DlColor::kBlue());
1217 }));
1218 RenderWith( //
1219 testP, env, tolerance,
1220 CaseParameters(
1221 "Color == Green",
1222 [=](const DlSetupContext& ctx) {
1223 ctx.paint.setColor(DlColor::kGreen());
1224 }));
1225 // clang-format on
1226
1227 RenderWithStrokes(testP, env, tolerance);
1228
1229 {
1230 // half opaque cyan
1231 DlColor blendable_color = DlColor::kCyan().withAlpha(0x7f);
1232 DlColor bg = DlColor::kWhite();
1233
1234 // clang-format off
1235 // The following section gets re-formatted on every commit even if it
1236 // doesn't change.
1237 RenderWith(testP, env, tolerance,
1238 CaseParameters(
1239 "Blend == SrcIn",
1240 [=](const DlSetupContext& ctx) {
1241 ctx.paint.setBlendMode(DlBlendMode::kSrcIn);
1242 ctx.paint.setColor(blendable_color);
1243 })
1244 .with_bg(bg));
1245 RenderWith(testP, env, tolerance,
1246 CaseParameters(
1247 "Blend == DstIn",
1248 [=](const DlSetupContext& ctx) {
1249 ctx.paint.setBlendMode(DlBlendMode::kDstIn);
1250 ctx.paint.setColor(blendable_color);
1251 })
1252 .with_bg(bg));
1253 // clang-format on
1254 }
1255
1256 {
1257 // Being able to see a blur requires some non-default attributes,
1258 // like a non-trivial stroke width and a shader rather than a color
1259 // (for drawPaint) so we create a new environment for these tests.
1260 RenderEnvironment blur_env =
1261 RenderEnvironment::MakeN32(env.GetProvider());
1262 DlSetup dl_blur_setup = [=](const DlSetupContext& ctx) {
1263 ctx.paint.setColorSource(MakeColorSource(ctx.env.GetTestImage()));
1264 ctx.paint.setStrokeWidth(5.0);
1265 };
1266 blur_env.InitializeReference(dl_blur_setup, testP.dl_renderer());
1267
1268 DlBlurImageFilter dl_filter_decal_5(5.0, 5.0, DlTileMode::kDecal);
1269 BoundsTolerance blur_5_tolerance = tolerance.addBoundsPadding(4, 4);
1270 {
1271 // clang-format off
1272 // The following section gets re-formatted on every commit even if it
1273 // doesn't change.
1274 RenderWith(testP, blur_env, blur_5_tolerance,
1275 CaseParameters(
1276 "ImageFilter == Decal Blur 5",
1277 [=](const DlSetupContext& ctx) {
1278 dl_blur_setup(ctx);
1279 ctx.paint.setImageFilter(&dl_filter_decal_5);
1280 }));
1281 // clang-format on
1282 }
1283 DlBlurImageFilter dl_filter_clamp_5(5.0, 5.0, DlTileMode::kClamp);
1284 {
1285 // clang-format off
1286 // The following section gets re-formatted on every commit even if it
1287 // doesn't change.
1288 RenderWith(testP, blur_env, blur_5_tolerance,
1289 CaseParameters(
1290 "ImageFilter == Clamp Blur 5",
1291 [=](const DlSetupContext& ctx) {
1292 dl_blur_setup(ctx);
1293 ctx.paint.setImageFilter(&dl_filter_clamp_5);
1294 }));
1295 // clang-format on
1296 }
1297 }
1298
1299 {
1300 // Being able to see a dilate requires some non-default attributes,
1301 // like a non-trivial stroke width and a shader rather than a color
1302 // (for drawPaint) so we create a new environment for these tests.
1303 RenderEnvironment dilate_env =
1304 RenderEnvironment::MakeN32(env.GetProvider());
1305 DlSetup dl_dilate_setup = [=](const DlSetupContext& ctx) {
1306 ctx.paint.setColorSource(MakeColorSource(ctx.env.GetTestImage()));
1307 ctx.paint.setStrokeWidth(5.0);
1308 };
1309 dilate_env.InitializeReference(dl_dilate_setup, testP.dl_renderer());
1310
1311 DlDilateImageFilter dl_dilate_filter_5(5.0, 5.0);
1312 // clang-format off
1313 // The following section gets re-formatted on every commit even if it
1314 // doesn't change.
1315 RenderWith(testP, dilate_env, tolerance,
1316 CaseParameters(
1317 "ImageFilter == Dilate 5",
1318 [=](const DlSetupContext& ctx) {
1319 dl_dilate_setup(ctx);
1320 ctx.paint.setImageFilter(&dl_dilate_filter_5);
1321 }));
1322 // clang-format on
1323 }
1324
1325 {
1326 // Being able to see an erode requires some non-default attributes,
1327 // like a non-trivial stroke width and a shader rather than a color
1328 // (for drawPaint) so we create a new environment for these tests.
1329 RenderEnvironment erode_env =
1330 RenderEnvironment::MakeN32(env.GetProvider());
1331 DlSetup dl_erode_setup = [=](const DlSetupContext& ctx) {
1332 ctx.paint.setColorSource(MakeColorSource(ctx.env.GetTestImage()));
1333 ctx.paint.setStrokeWidth(6.0);
1334 };
1335 erode_env.InitializeReference(dl_erode_setup, testP.dl_renderer());
1336
1337 // do not erode too much, because some tests assert there are enough
1338 // pixels that are changed.
1339 DlErodeImageFilter dl_erode_filter_1(1.0, 1.0);
1340 // clang-format off
1341 // The following section gets re-formatted on every commit even if it
1342 // doesn't change.
1343 RenderWith(testP, erode_env, tolerance,
1344 CaseParameters(
1345 "ImageFilter == Erode 1",
1346 [=](const DlSetupContext& ctx) {
1347 dl_erode_setup(ctx);
1348 ctx.paint.setImageFilter(&dl_erode_filter_1);
1349 }));
1350 // clang-format on
1351 }
1352
1353 {
1354 // clang-format off
1355 constexpr float rotate_color_matrix[20] = {
1356 0, 1, 0, 0, 0,
1357 0, 0, 1, 0, 0,
1358 1, 0, 0, 0, 0,
1359 0, 0, 0, 1, 0,
1360 };
1361 // clang-format on
1362 std::shared_ptr<const DlColorFilter> dl_color_filter =
1363 DlColorFilter::MakeMatrix(rotate_color_matrix);
1364 {
1365 DlColor bg = DlColor::kWhite();
1366 // clang-format off
1367 // The following section gets re-formatted on every commit even if it
1368 // doesn't change.
1369 RenderWith(testP, env, tolerance,
1370 CaseParameters(
1371 "ColorFilter == RotateRGB",
1372 [=](const DlSetupContext& ctx) {
1373 ctx.paint.setColor(DlColor::kYellow());
1374 ctx.paint.setColorFilter(dl_color_filter);
1375 })
1376 .with_bg(bg));
1377 // clang-format on
1378 }
1379 {
1380 DlColor bg = DlColor::kWhite();
1381 // clang-format off
1382 // The following section gets re-formatted on every commit even if it
1383 // doesn't change.
1384 RenderWith(testP, env, tolerance,
1385 CaseParameters(
1386 "ColorFilter == Invert",
1387 [=](const DlSetupContext& ctx) {
1388 ctx.paint.setColor(DlColor::kYellow());
1389 ctx.paint.setInvertColors(true);
1390 })
1391 .with_bg(bg));
1392 // clang-format on
1393 }
1394 }
1395
1396 {
1397 const DlBlurMaskFilter dl_mask_filter(DlBlurStyle::kNormal, 5.0);
1398 BoundsTolerance blur_5_tolerance = tolerance.addBoundsPadding(4, 4);
1399 {
1400 // clang-format off
1401 // The following section gets re-formatted on every commit even if it
1402 // doesn't change.
1403 RenderWith(testP, env, blur_5_tolerance,
1404 CaseParameters(
1405 "MaskFilter == Blur 5",
1406 [=](const DlSetupContext& ctx) {
1407 // Stroked primitives need some non-trivial stroke
1408 // width to be blurred
1409 ctx.paint.setStrokeWidth(5.0);
1410 ctx.paint.setMaskFilter(&dl_mask_filter);
1411 }));
1412 // clang-format on
1413 }
1414 }
1415
1416 {
1417 DlPoint dl_end_points[] = {
1420 };
1421 DlColor dl_colors[] = {
1425 };
1426 float stops[] = {
1427 0.0,
1428 0.5,
1429 1.0,
1430 };
1431 std::shared_ptr<DlColorSource> dl_gradient =
1432 DlColorSource::MakeLinear(dl_end_points[0], dl_end_points[1], 3,
1433 dl_colors, stops, DlTileMode::kMirror);
1434 {
1435 // clang-format off
1436 // The following section gets re-formatted on every commit even if it
1437 // doesn't change.
1438 RenderWith(testP, env, tolerance,
1439 CaseParameters(
1440 "LinearGradient GYB",
1441 [=](const DlSetupContext& ctx) {
1442 ctx.paint.setColorSource(dl_gradient);
1443 }));
1444 // clang-format on
1445 }
1446 }
1447 }
static std::shared_ptr< const DlColorFilter > MakeMatrix(const float matrix[20])
static std::shared_ptr< DlColorSource > MakeLinear(const DlPoint start_point, const DlPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
static void RenderWithStrokes(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance_in)
static void RenderWith(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance_in, const CaseParameters &caseP)
constexpr DlRect kRenderBounds
const std::function< void(const DlSetupContext &)> DlSetup
static std::shared_ptr< DlImageColorSource > MakeColorSource(const sk_sp< DlImage > &image)
@ kNormal
fuzzy inside and outside
impeller::Point DlPoint
static constexpr DlColor kWhite()
Definition dl_color.h:70
static constexpr DlColor kBlue()
Definition dl_color.h:73
static constexpr DlColor kYellow()
Definition dl_color.h:76
static constexpr DlColor kGreen()
Definition dl_color.h:72
static constexpr DlColor kCyan()
Definition dl_color.h:74
DlColor withAlpha(uint8_t alpha) const
Definition dl_color.h:120
constexpr TPoint< T > GetLeftTop() const
Definition rect.h:393
constexpr TPoint< T > GetRightBottom() const
Definition rect.h:405

References flutter::testing::BoundsTolerance::addBoundsPadding(), flutter::testing::DlSetupContext::canvas, flutter::testing::TestParameters::dl_renderer(), flutter::testing::DlSetupContext::env, impeller::TRect< T >::GetLeftTop(), flutter::testing::RenderEnvironment::GetProvider(), impeller::TRect< T >::GetRightBottom(), flutter::testing::RenderEnvironment::GetTestImage(), flutter::testing::RenderEnvironment::InitializeReference(), flutter::DlColor::kBlue(), flutter::kClamp, flutter::DlColor::kCyan(), flutter::kDecal, flutter::DlColor::kGreen(), flutter::kMirror, flutter::kNormal, flutter::testing::kRenderBounds, flutter::DlColor::kWhite(), flutter::DlColor::kYellow(), flutter::testing::MakeColorSource(), flutter::DlColorSource::MakeLinear(), flutter::DlColorFilter::MakeMatrix(), flutter::testing::RenderEnvironment::MakeN32(), flutter::testing::DlSetupContext::paint, RenderWith(), RenderWithStrokes(), flutter::DlPaint::setAntiAlias(), flutter::DlPaint::setBlendMode(), flutter::DlPaint::setColor(), flutter::DlPaint::setColorFilter(), flutter::DlPaint::setColorSource(), flutter::DlPaint::setImageFilter(), flutter::DlPaint::setInvertColors(), flutter::DlPaint::setMaskFilter(), flutter::DlPaint::setStrokeWidth(), flutter::DlCanvas::Translate(), and flutter::DlColor::withAlpha().

Referenced by RenderAll().

◆ RenderWithClips()

static void flutter::testing::CanvasCompareTester::RenderWithClips ( const TestParameters testP,
const RenderEnvironment env,
const BoundsTolerance diff_tolerance 
)
inlinestatic

Definition at line 1681 of file dl_rendering_unittests.cc.

1683 {
1684 // We used to use an inset of 15.5 pixels here, but since Skia's rounding
1685 // behavior at the center of pixels does not match between HW and SW, we
1686 // ended up with some clips including different pixels between the two
1687 // destinations and this interacted poorly with the carefully chosen
1688 // geometry in some of the tests which was designed to have just the
1689 // right features fully filling the clips based on the SW rounding. By
1690 // moving to a 15.4 inset, the edge of the clip is never on the "rounding
1691 // edge" of a pixel.
1692 DlRect r_clip = kRenderBounds.Expand(-15.4, -15.4);
1693 BoundsTolerance intersect_tolerance = diff_tolerance.clip(r_clip);
1694 intersect_tolerance = intersect_tolerance.addPostClipPadding(1, 1);
1695 // clang-format off
1696 // The following section gets re-formatted on every commit even if it
1697 // doesn't change.
1698 RenderWith(testP, env, intersect_tolerance,
1699 CaseParameters(
1700 "Hard ClipRect inset by 15.4",
1701 [=](const DlSetupContext& ctx) {
1702 ctx.canvas->ClipRect(r_clip, DlClipOp::kIntersect, false);
1703 }));
1704 RenderWith(testP, env, intersect_tolerance,
1705 CaseParameters(
1706 "AntiAlias ClipRect inset by 15.4",
1707 [=](const DlSetupContext& ctx) {
1708 ctx.canvas->ClipRect(r_clip, DlClipOp::kIntersect, true);
1709 }));
1710 RenderWith(testP, env, diff_tolerance,
1711 CaseParameters(
1712 "Hard ClipRect Diff, inset by 15.4",
1713 [=](const DlSetupContext& ctx) {
1714 ctx.canvas->ClipRect(r_clip, DlClipOp::kDifference, false);
1715 })
1716 .with_diff_clip());
1717 RenderWith(testP, env, intersect_tolerance,
1718 CaseParameters(
1719 "Hard ClipOval",
1720 [=](const DlSetupContext& ctx) {
1721 ctx.canvas->ClipOval(r_clip, DlClipOp::kIntersect, false);
1722 }));
1723 RenderWith(testP, env, intersect_tolerance,
1724 CaseParameters(
1725 "AntiAlias ClipOval",
1726 [=](const DlSetupContext& ctx) {
1727 ctx.canvas->ClipOval(r_clip, DlClipOp::kIntersect, true);
1728 }));
1729 RenderWith(testP, env, diff_tolerance,
1730 CaseParameters(
1731 "Hard ClipOval Diff",
1732 [=](const DlSetupContext& ctx) {
1733 ctx.canvas->ClipOval(r_clip, DlClipOp::kDifference, false);
1734 })
1735 .with_diff_clip());
1736 // clang-format on
1737
1738 // This test RR clip used to use very small radii, but due to
1739 // optimizations in the HW rrect rasterization, this caused small
1740 // bulges in the corners of the RRect which were interpreted as
1741 // "clip overruns" by the clip OOB pixel testing code. Using less
1742 // abusively small radii fixes the problem.
1743 DlRoundRect rr_clip = DlRoundRect::MakeRectXY(r_clip, 9, 9);
1744 // clang-format off
1745 // The following section gets re-formatted on every commit even if it
1746 // doesn't change.
1747 RenderWith(testP, env, intersect_tolerance,
1748 CaseParameters(
1749 "Hard ClipRRect with radius of 9",
1750 [=](const DlSetupContext& ctx) {
1751 ctx.canvas->ClipRoundRect(rr_clip, DlClipOp::kIntersect,
1752 false);
1753 }));
1754 RenderWith(testP, env, intersect_tolerance,
1755 CaseParameters(
1756 "AntiAlias ClipRRect with radius of 9",
1757 [=](const DlSetupContext& ctx) {
1758 ctx.canvas->ClipRoundRect(rr_clip, DlClipOp::kIntersect,
1759 true);
1760 }));
1761 RenderWith(testP, env, diff_tolerance,
1762 CaseParameters(
1763 "Hard ClipRRect Diff, with radius of 9",
1764 [=](const DlSetupContext& ctx) {
1765 ctx.canvas->ClipRoundRect(rr_clip, DlClipOp::kDifference,
1766 false);
1767 })
1768 .with_diff_clip());
1769 // clang-format on
1770
1771 DlPathBuilder path_builder;
1772 path_builder.SetFillType(DlPathFillType::kOdd);
1773 path_builder.AddRect(r_clip);
1774 path_builder.AddCircle(DlPoint(kRenderCenterX, kRenderCenterY), 1.0f);
1775 DlPath path_clip = path_builder.TakePath();
1776 // clang-format off
1777 // The following section gets re-formatted on every commit even if it
1778 // doesn't change.
1779 RenderWith(testP, env, intersect_tolerance,
1780 CaseParameters(
1781 "Hard ClipPath inset by 15.4",
1782 [=](const DlSetupContext& ctx) {
1783 ctx.canvas->ClipPath(path_clip, DlClipOp::kIntersect,
1784 false);
1785 }));
1786 RenderWith(testP, env, intersect_tolerance,
1787 CaseParameters(
1788 "AntiAlias ClipPath inset by 15.4",
1789 [=](const DlSetupContext& ctx) {
1790 ctx.canvas->ClipPath(path_clip, DlClipOp::kIntersect,
1791 true);
1792 }));
1793 RenderWith(testP, env, diff_tolerance,
1794 CaseParameters(
1795 "Hard ClipPath Diff, inset by 15.4",
1796 [=](const DlSetupContext& ctx) {
1797 ctx.canvas->ClipPath(path_clip, DlClipOp::kDifference,
1798 false);
1799 })
1800 .with_diff_clip());
1801 // clang-format off
1802 }
constexpr DlScalar kRenderCenterY
constexpr DlScalar kRenderCenterX
impeller::RoundRect DlRoundRect
flutter::DlPath DlPath
static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition round_rect.h:31
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition rect.h:652

References flutter::DlPathBuilder::AddCircle(), flutter::testing::BoundsTolerance::addPostClipPadding(), flutter::DlPathBuilder::AddRect(), flutter::testing::DlSetupContext::canvas, flutter::testing::BoundsTolerance::clip(), flutter::DlCanvas::ClipOval(), flutter::DlCanvas::ClipPath(), flutter::DlCanvas::ClipRect(), flutter::DlCanvas::ClipRoundRect(), impeller::TRect< T >::Expand(), flutter::kDifference, flutter::kIntersect, flutter::testing::kRenderBounds, flutter::testing::kRenderCenterX, flutter::testing::kRenderCenterY, impeller::RoundRect::MakeRectXY(), RenderWith(), flutter::DlPathBuilder::SetFillType(), and flutter::DlPathBuilder::TakePath().

Referenced by RenderAll().

◆ RenderWithSaveRestore()

static void flutter::testing::CanvasCompareTester::RenderWithSaveRestore ( const TestParameters testP,
const RenderEnvironment env,
const BoundsTolerance tolerance 
)
inlinestatic

Definition at line 947 of file dl_rendering_unittests.cc.

949 {
950 DlRect clip =
953 DlColor alpha_layer_color = DlColor::kCyan().withAlpha(0x7f);
954 DlRenderer dl_safe_restore = [=](const DlRenderContext& ctx) {
955 // Draw another primitive to disable peephole optimizations
956 // As the rendering op rejection in the DisplayList Builder
957 // gets smarter and smarter, this operation has had to get
958 // sneakier and sneakier about specifying an operation that
959 // won't practically show up in the output, but technically
960 // can't be culled.
961 ctx.canvas->DrawRect(
963 DlPaint());
964 ctx.canvas->Restore();
965 };
966 DlRenderer dl_opt_restore = [=](const DlRenderContext& ctx) {
967 // Just a simple restore to allow peephole optimizations to occur
968 ctx.canvas->Restore();
969 };
970 DlRect layer_bounds = kRenderBounds.Expand(-15, -15);
971 // clang-format off
972 // The following section gets re-formatted on every commit even if it
973 // doesn't change.
974 RenderWith(testP, env, tolerance,
975 CaseParameters(
976 "With prior save/clip/restore",
977 [=](const DlSetupContext& ctx) {
978 ctx.canvas->Save();
979 ctx.canvas->ClipRect(clip, DlClipOp::kIntersect, false);
980 DlPaint p2;
981 ctx.canvas->DrawRect(rect, p2);
982 p2.setBlendMode(DlBlendMode::kClear);
983 ctx.canvas->DrawRect(rect, p2);
984 ctx.canvas->Restore();
985 }));
986 RenderWith(testP, env, tolerance,
987 CaseParameters(
988 "saveLayer no paint, no bounds",
989 [=](const DlSetupContext& ctx) {
990 ctx.canvas->SaveLayer(std::nullopt, nullptr);
991 })
992 .with_restore(dl_safe_restore, false));
993 RenderWith(testP, env, tolerance,
994 CaseParameters(
995 "saveLayer no paint, with bounds",
996 [=](const DlSetupContext& ctx) {
997 ctx.canvas->SaveLayer(layer_bounds, nullptr);
998 })
999 .with_restore(dl_safe_restore, true));
1000 RenderWith(testP, env, tolerance,
1001 CaseParameters(
1002 "saveLayer with alpha, no bounds",
1003 [=](const DlSetupContext& ctx) {
1004 DlPaint save_p;
1005 save_p.setColor(alpha_layer_color);
1006 ctx.canvas->SaveLayer(std::nullopt, &save_p);
1007 })
1008 .with_restore(dl_safe_restore, true));
1009 RenderWith(testP, env, tolerance,
1010 CaseParameters(
1011 "saveLayer with peephole alpha, no bounds",
1012 [=](const DlSetupContext& ctx) {
1013 DlPaint save_p;
1014 save_p.setColor(alpha_layer_color);
1015 ctx.canvas->SaveLayer(std::nullopt, &save_p);
1016 })
1017 .with_restore(dl_opt_restore, true, true));
1018 RenderWith(testP, env, tolerance,
1019 CaseParameters(
1020 "saveLayer with alpha and bounds",
1021 [=](const DlSetupContext& ctx) {
1022 DlPaint save_p;
1023 save_p.setColor(alpha_layer_color);
1024 ctx.canvas->SaveLayer(layer_bounds, &save_p);
1025 })
1026 .with_restore(dl_safe_restore, true));
1027 // clang-format on
1028 {
1029 // Being able to see a backdrop blur requires a non-default background
1030 // so we create a new environment for these tests that has a checkerboard
1031 // background that can be blurred by the backdrop filter. We also want
1032 // to avoid the rendered primitive from obscuring the blurred background
1033 // so we set an alpha value which works for all primitives except for
1034 // drawColor which can override the alpha with its color, but it now uses
1035 // a non-opaque color to avoid that problem.
1036 RenderEnvironment backdrop_env =
1037 RenderEnvironment::MakeN32(env.GetProvider());
1038 DlSetup dl_backdrop_setup = [=](const DlSetupContext& ctx) {
1039 DlPaint setup_p;
1040 setup_p.setColorSource(MakeColorSource(ctx.env.GetTestImage()));
1041 ctx.canvas->DrawPaint(setup_p);
1042 };
1043 DlSetup dl_content_setup = [=](const DlSetupContext& ctx) {
1044 ctx.paint.setAlpha(ctx.paint.getAlpha() / 2);
1045 };
1046 backdrop_env.InitializeReference(dl_backdrop_setup, testP.dl_renderer());
1047
1048 DlBlurImageFilter dl_backdrop(5, 5, DlTileMode::kDecal);
1049 // clang-format off
1050 // The following section gets re-formatted on every commit even if it
1051 // doesn't change.
1052 RenderWith(
1053 testP, backdrop_env, tolerance,
1054 CaseParameters(
1055 "saveLayer with backdrop",
1056 [=](const DlSetupContext& ctx) {
1057 dl_backdrop_setup(ctx);
1058 ctx.canvas->SaveLayer(std::nullopt, nullptr, &dl_backdrop);
1059 dl_content_setup(ctx);
1060 })
1061 .with_restore(dl_safe_restore, true));
1062 RenderWith(testP, backdrop_env, tolerance,
1063 CaseParameters(
1064 "saveLayer with bounds and backdrop",
1065 [=](const DlSetupContext& ctx) {
1066 dl_backdrop_setup(ctx);
1067 ctx.canvas->SaveLayer(layer_bounds, nullptr,
1068 &dl_backdrop);
1069 dl_content_setup(ctx);
1070 })
1071 .with_restore(dl_safe_restore, true));
1072 RenderWith(
1073 testP, backdrop_env, tolerance,
1074 CaseParameters(
1075 "clipped saveLayer with backdrop",
1076 [=](const DlSetupContext& ctx) {
1077 dl_backdrop_setup(ctx);
1078 ctx.canvas->ClipRect(layer_bounds);
1079 ctx.canvas->SaveLayer(std::nullopt, nullptr, &dl_backdrop);
1080 dl_content_setup(ctx);
1081 })
1082 .with_restore(dl_safe_restore, true));
1083 // clang-format on
1084 }
1085
1086 {
1087 // clang-format off
1088 constexpr float rotate_alpha_color_matrix[20] = {
1089 0, 1, 0, 0 , 0,
1090 0, 0, 1, 0 , 0,
1091 1, 0, 0, 0 , 0,
1092 0, 0, 0, 0.5, 0,
1093 };
1094 // clang-format on
1095 std::shared_ptr<const DlColorFilter> dl_alpha_rotate_filter =
1096 DlColorFilter::MakeMatrix(rotate_alpha_color_matrix);
1097 // clang-format off
1098 // The following section gets re-formatted on every commit even if it
1099 // doesn't change.
1100 {
1101 RenderWith(testP, env, tolerance,
1102 CaseParameters(
1103 "saveLayer ColorFilter, no bounds",
1104 [=](const DlSetupContext& ctx) {
1105 DlPaint save_p;
1106 save_p.setColorFilter(dl_alpha_rotate_filter);
1107 ctx.canvas->SaveLayer(std::nullopt, &save_p);
1108 ctx.paint.setStrokeWidth(5.0);
1109 })
1110 .with_restore(dl_safe_restore, true));
1111 }
1112 {
1113 RenderWith(testP, env, tolerance,
1114 CaseParameters(
1115 "saveLayer ColorFilter and bounds",
1116 [=](const DlSetupContext& ctx) {
1117 DlPaint save_p;
1118 save_p.setColorFilter(dl_alpha_rotate_filter);
1119 ctx.canvas->SaveLayer(kRenderBounds, &save_p);
1120 ctx.paint.setStrokeWidth(5.0);
1121 })
1122 .with_restore(dl_safe_restore, true));
1123 }
1124 // clang-format on
1125 }
1126
1127 {
1128 // clang-format off
1129 constexpr float color_matrix[20] = {
1130 0.5, 0, 0, 0, 0.5,
1131 0, 0.5, 0, 0, 0.5,
1132 0, 0, 0.5, 0, 0.5,
1133 0, 0, 0, 1, 0,
1134 };
1135 // clang-format on
1136 std::shared_ptr<const DlColorFilter> dl_color_filter =
1137 DlColorFilter::MakeMatrix(color_matrix);
1138 std::shared_ptr<DlImageFilter> dl_cf_image_filter =
1139 DlImageFilter::MakeColorFilter(dl_color_filter);
1140 // clang-format off
1141 // The following section gets re-formatted on every commit even if it
1142 // doesn't change.
1143 {
1144 RenderWith(testP, env, tolerance,
1145 CaseParameters(
1146 "saveLayer ImageFilter, no bounds",
1147 [=](const DlSetupContext& ctx) {
1148 DlPaint save_p;
1149 save_p.setImageFilter(dl_cf_image_filter);
1150 ctx.canvas->SaveLayer(std::nullopt, &save_p);
1151 ctx.paint.setStrokeWidth(5.0);
1152 })
1153 .with_restore(dl_safe_restore, true));
1154 }
1155 {
1156 RenderWith(testP, env, tolerance,
1157 CaseParameters(
1158 "saveLayer ImageFilter and bounds",
1159 [=](const DlSetupContext& ctx) {
1160 DlPaint save_p;
1161 save_p.setImageFilter(dl_cf_image_filter);
1162 ctx.canvas->SaveLayer(kRenderBounds, &save_p);
1163 ctx.paint.setStrokeWidth(5.0);
1164 })
1165 .with_restore(dl_safe_restore, true));
1166 }
1167 // clang-format on
1168 }
1169 }
static std::shared_ptr< DlImageFilter > MakeColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setAlpha(uint8_t alpha)
Definition dl_paint.h:76
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:85
DlPaint & setImageFilter(std::nullptr_t filter)
Definition dl_paint.h:167
DlPaint & setColorFilter(std::nullptr_t filter)
Definition dl_paint.h:149
DlPaint & setColorSource(std::nullptr_t source)
Definition dl_paint.h:131
const std::function< void(const DlRenderContext &)> DlRenderer
flutter::DlPaint DlPaint
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136

References flutter::testing::DlSetupContext::canvas, flutter::DlCanvas::ClipRect(), flutter::testing::TestParameters::dl_renderer(), flutter::DlCanvas::DrawPaint(), flutter::DlCanvas::DrawRect(), flutter::testing::DlSetupContext::env, impeller::TRect< T >::Expand(), flutter::DlPaint::getAlpha(), flutter::testing::RenderEnvironment::GetProvider(), flutter::testing::RenderEnvironment::GetTestImage(), flutter::testing::RenderEnvironment::InitializeReference(), flutter::DlColor::kCyan(), flutter::kDecal, flutter::kIntersect, flutter::testing::kRenderBounds, flutter::testing::kRenderCenterX, flutter::testing::kRenderCenterY, flutter::DlImageFilter::MakeColorFilter(), flutter::testing::MakeColorSource(), flutter::DlColorFilter::MakeMatrix(), flutter::testing::RenderEnvironment::MakeN32(), impeller::TRect< Scalar >::MakeXYWH(), p2, flutter::testing::DlSetupContext::paint, RenderWith(), flutter::DlCanvas::Restore(), flutter::DlCanvas::Save(), flutter::DlCanvas::SaveLayer(), flutter::DlPaint::setAlpha(), flutter::DlPaint::setColor(), flutter::DlPaint::setColorFilter(), flutter::DlPaint::setColorSource(), flutter::DlPaint::setImageFilter(), flutter::DlPaint::setStrokeWidth(), and flutter::DlColor::withAlpha().

Referenced by RenderAll().

◆ RenderWithStrokes()

static void flutter::testing::CanvasCompareTester::RenderWithStrokes ( const TestParameters testP,
const RenderEnvironment env,
const BoundsTolerance tolerance_in 
)
inlinestatic

Definition at line 1449 of file dl_rendering_unittests.cc.

1451 {
1452 // The test cases were generated with geometry that will try to fill
1453 // out the various miter limits used for testing, but they can be off
1454 // by a couple of pixels so we will relax bounds testing for strokes by
1455 // a couple of pixels.
1456
1457 // clang-format off
1458 // The following section gets re-formatted on every commit even if it
1459 // doesn't change.
1460 BoundsTolerance tolerance = tolerance_in.addBoundsPadding(2, 2);
1461 RenderWith(testP, env, tolerance,
1462 CaseParameters(
1463 "Fill",
1464 [=](const DlSetupContext& ctx) {
1465 ctx.paint.setDrawStyle(DlDrawStyle::kFill);
1466 }));
1467 // clang-format on
1468
1469 // Skia on HW produces a strong miter consistent with width=1.0
1470 // for any width less than a pixel, but the bounds computations of
1471 // both DL and SkPicture do not account for this. We will get
1472 // OOB pixel errors for the highly mitered drawPath geometry if
1473 // we don't set stroke width to 1.0 for that test on HW.
1474 // See https://bugs.chromium.org/p/skia/issues/detail?id=14046
1475 bool no_hairlines =
1476 testP.is_draw_path() &&
1477 env.GetProvider()->GetBackendType() != BackendType::kSkiaSoftware;
1478 // clang-format off
1479 // The following section gets re-formatted on every commit even if it
1480 // doesn't change.
1481 RenderWith(testP, env, tolerance,
1482 CaseParameters(
1483 "Stroke + defaults",
1484 [=](const DlSetupContext& ctx) {
1485 if (no_hairlines) {
1486 ctx.paint.setStrokeWidth(1.0);
1487 }
1488 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1489 }));
1490
1491 RenderWith(testP, env, tolerance,
1492 CaseParameters(
1493 "Fill + unnecessary StrokeWidth 10",
1494 [=](const DlSetupContext& ctx) {
1495 ctx.paint.setDrawStyle(DlDrawStyle::kFill);
1496 ctx.paint.setStrokeWidth(10.0);
1497 }));
1498 // clang-format on
1499
1500 RenderEnvironment stroke_base_env =
1501 RenderEnvironment::MakeN32(env.GetProvider());
1502 DlSetup dl_stroke_setup = [=](const DlSetupContext& ctx) {
1503 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1504 ctx.paint.setStrokeWidth(5.0);
1505 };
1506 stroke_base_env.InitializeReference(dl_stroke_setup, testP.dl_renderer());
1507
1508 // clang-format off
1509 // The following section gets re-formatted on every commit even if it
1510 // doesn't change.
1511 RenderWith(testP, stroke_base_env, tolerance,
1512 CaseParameters(
1513 "Stroke Width 10",
1514 [=](const DlSetupContext& ctx) {
1515 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1516 ctx.paint.setStrokeWidth(10.0);
1517 }));
1518 RenderWith(testP, stroke_base_env, tolerance,
1519 CaseParameters(
1520 "Stroke Width 5",
1521 [=](const DlSetupContext& ctx) {
1522 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1523 ctx.paint.setStrokeWidth(5.0);
1524 }));
1525
1526 RenderWith(testP, stroke_base_env, tolerance,
1527 CaseParameters(
1528 "Stroke Width 5, Square Cap",
1529 [=](const DlSetupContext& ctx) {
1530 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1531 ctx.paint.setStrokeWidth(5.0);
1532 ctx.paint.setStrokeCap(DlStrokeCap::kSquare);
1533 }));
1534 RenderWith(testP, stroke_base_env, tolerance,
1535 CaseParameters(
1536 "Stroke Width 5, Round Cap",
1537 [=](const DlSetupContext& ctx) {
1538 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1539 ctx.paint.setStrokeWidth(5.0);
1540 ctx.paint.setStrokeCap(DlStrokeCap::kRound);
1541 }));
1542
1543 RenderWith(testP, stroke_base_env, tolerance,
1544 CaseParameters(
1545 "Stroke Width 5, Bevel Join",
1546 [=](const DlSetupContext& ctx) {
1547 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1548 ctx.paint.setStrokeWidth(5.0);
1549 ctx.paint.setStrokeJoin(DlStrokeJoin::kBevel);
1550 }));
1551 RenderWith(testP, stroke_base_env, tolerance,
1552 CaseParameters(
1553 "Stroke Width 5, Round Join",
1554 [=](const DlSetupContext& ctx) {
1555 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1556 ctx.paint.setStrokeWidth(5.0);
1557 ctx.paint.setStrokeJoin(DlStrokeJoin::kRound);
1558 }));
1559
1560 RenderWith(testP, stroke_base_env, tolerance,
1561 CaseParameters(
1562 "Stroke Width 5, Miter 10",
1563 [=](const DlSetupContext& ctx) {
1564 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1565 ctx.paint.setStrokeWidth(5.0);
1566 ctx.paint.setStrokeMiter(10.0);
1567 ctx.paint.setStrokeJoin(DlStrokeJoin::kMiter);
1568 }));
1569
1570 RenderWith(testP, stroke_base_env, tolerance,
1571 CaseParameters(
1572 "Stroke Width 5, Miter 0",
1573 [=](const DlSetupContext& ctx) {
1574 ctx.paint.setDrawStyle(DlDrawStyle::kStroke);
1575 ctx.paint.setStrokeWidth(5.0);
1576 ctx.paint.setStrokeMiter(0.0);
1577 ctx.paint.setStrokeJoin(DlStrokeJoin::kMiter);
1578 }));
1579 // clang-format on
1580 }
@ kMiter
extends to miter limit
@ kBevel
connects outside edges
@ kRound
adds circle
@ kSquare
adds square
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes

References flutter::testing::BoundsTolerance::addBoundsPadding(), flutter::testing::TestParameters::dl_renderer(), flutter::testing::DlSurfaceProvider::GetBackendType(), flutter::testing::RenderEnvironment::GetProvider(), flutter::testing::RenderEnvironment::InitializeReference(), flutter::testing::TestParameters::is_draw_path(), flutter::kBevel, flutter::kFill, flutter::kMiter, flutter::kRound, flutter::kSquare, flutter::kStroke, flutter::testing::RenderEnvironment::MakeN32(), flutter::testing::DlSetupContext::paint, RenderWith(), flutter::DlPaint::setDrawStyle(), flutter::DlPaint::setStrokeCap(), flutter::DlPaint::setStrokeJoin(), flutter::DlPaint::setStrokeMiter(), and flutter::DlPaint::setStrokeWidth().

Referenced by RenderWithAttributes().

◆ RenderWithTransforms()

static void flutter::testing::CanvasCompareTester::RenderWithTransforms ( const TestParameters testP,
const RenderEnvironment env,
const BoundsTolerance tolerance 
)
inlinestatic

Definition at line 1582 of file dl_rendering_unittests.cc.

1584 {
1585 // If the rendering method does not fill the corners of the original
1586 // bounds, then the estimate under rotation or skewing will be off
1587 // so we scale the padding by about 5% to compensate.
1588 BoundsTolerance skewed_tolerance = tolerance.mulScale(1.05, 1.05);
1589 RenderWith( //
1590 testP, env, tolerance,
1591 CaseParameters(
1592 "Translate 5, 10", //
1593 [=](const DlSetupContext& ctx) { ctx.canvas->Translate(5, 10); }));
1594 RenderWith( //
1595 testP, env, tolerance,
1596 CaseParameters(
1597 "Scale +5%", //
1598 [=](const DlSetupContext& ctx) { ctx.canvas->Scale(1.05, 1.05); }));
1599 RenderWith( //
1600 testP, env, skewed_tolerance,
1601 CaseParameters(
1602 "Rotate 5 degrees", //
1603 [=](const DlSetupContext& ctx) { ctx.canvas->Rotate(5); }));
1604 RenderWith( //
1605 testP, env, skewed_tolerance,
1606 CaseParameters(
1607 "Skew 5%", //
1608 [=](const DlSetupContext& ctx) { ctx.canvas->Skew(0.05, 0.05); }));
1609 {
1610 // This rather odd transform can cause slight differences in
1611 // computing in-bounds samples depending on which base rendering
1612 // routine Skia uses. Making sure our matrix values are powers
1613 // of 2 reduces, but does not eliminate, these slight differences
1614 // in calculation when we are comparing rendering with an alpha
1615 // to rendering opaque colors in the group opacity tests, for
1616 // example.
1617 DlScalar tweak = 1.0 / 16.0;
1618 DlMatrix matrix = DlMatrix::MakeRow(
1619 // clang-format off
1620 1.0 + tweak, tweak, 0, 5,
1621 tweak, 1.0 + tweak, 0, 10,
1622 0, 0, 1, 0,
1623 0, 0, 0, 1
1624 // clang-format on
1625 );
1626 // clang-format off
1627 // The following section gets re-formatted on every commit even if it
1628 // doesn't change.
1629 RenderWith(
1630 testP, env, skewed_tolerance,
1631 CaseParameters(
1632 "Transform 2D Affine Matrix",
1633 [=](const DlSetupContext& ctx) {
1634 ctx.canvas->Transform(matrix);
1635 }));
1636 RenderWith(
1637 testP, env, skewed_tolerance,
1638 CaseParameters(
1639 "Transform 2D Affine inline",
1640 [=](const DlSetupContext& ctx) {
1641 ctx.canvas->Transform2DAffine(1.0 + tweak, tweak, 5,
1642 tweak, 1.0 + tweak, 10);
1643 }));
1644 // clang-format on
1645 }
1646 {
1647 DlMatrix matrix = DlMatrix::MakeRow(1.0f, 0.0f, 0.0f, kRenderCenterX, //
1648 0.0f, 1.0f, 0.0f, kRenderCenterY, //
1649 0.0f, 0.0f, 1.0f, 0.0f, //
1650 0.0f, 0.0f, .001f, 1.0f);
1651 matrix = matrix * DlMatrix::MakeRotationX(DlDegrees(3));
1652 matrix = matrix * DlMatrix::MakeRotationY(DlDegrees(4));
1653 matrix = matrix.Translate({-kRenderCenterX, -kRenderCenterY, 0.0f});
1654 // clang-format off
1655 // The following section gets re-formatted on every commit even if it
1656 // doesn't change.
1657 RenderWith(
1658 testP, env, skewed_tolerance,
1659 CaseParameters(
1660 "Transform Full Perspective Matrix",
1661 [=](const DlSetupContext& ctx) {
1662 ctx.canvas->Transform(matrix);
1663 }));
1664 RenderWith(
1665 testP, env, skewed_tolerance,
1666 CaseParameters(
1667 "Transform Full Perspective inline",
1668 [=](const DlSetupContext& ctx) {
1669 ctx.canvas->TransformFullPerspective(
1670 // These values match what ends up in matrix above
1671 0.997564, 0.000000, 0.069756, 0.243591,
1672 0.003651, 0.998630, -0.052208, -0.228027,
1673 -0.069661, 0.052336, 0.996197, 1.732491,
1674 -0.000070, 0.000052, 0.000996, 1.001732
1675 );
1676 }));
1677 // clang-format on
1678 }
1679 }
impeller::Matrix DlMatrix
impeller::Degrees DlDegrees
static Matrix MakeRotationY(Radians r)
Definition matrix.h:208
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition matrix.h:83
static Matrix MakeRotationX(Radians r)
Definition matrix.h:193

References flutter::testing::DlSetupContext::canvas, flutter::testing::kRenderCenterX, flutter::testing::kRenderCenterY, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRow(), flutter::testing::BoundsTolerance::mulScale(), RenderWith(), flutter::DlCanvas::Rotate(), flutter::DlCanvas::Scale(), flutter::DlCanvas::Skew(), flutter::DlCanvas::Transform(), flutter::DlCanvas::Transform2DAffine(), flutter::DlCanvas::TransformFullPerspective(), impeller::Matrix::Translate(), and flutter::DlCanvas::Translate().

Referenced by RenderAll().

◆ save_to_png()

static void flutter::testing::CanvasCompareTester::save_to_png ( const RenderResult result,
const std::string &  op_desc,
const std::string &  reason 
)
inlinestatic

Definition at line 1851 of file dl_rendering_unittests.cc.

1853 {
1854 if (!save_failure_images_) {
1855 return;
1856 }
1857 if (failure_image_directory_.length() == 0) {
1859 if (failure_image_directory_.length() == 0) {
1860 save_failure_images_ = false;
1861 return;
1862 }
1863 }
1864
1865 std::string filename = failure_image_directory_ + "/";
1866 for (const char& ch : op_desc) {
1867 filename += (ch == ':' || ch == ' ') ? '_' : ch;
1868 }
1869 filename = filename + ".png";
1870 if (!result.pixel_data->write(filename)) {
1871 FML_LOG(ERROR) << "Could not write output to " << filename;
1872 }
1873 failure_image_filenames_.push_back(filename);
1874 FML_LOG(ERROR) << reason << ": " << filename;
1875 }

References FML_LOG, flutter::testing::RenderResult::pixel_data, and SetupFailureImageDirectory().

Referenced by RenderWith().

◆ SetupFailureImageDirectory()

static void flutter::testing::CanvasCompareTester::SetupFailureImageDirectory ( )
inlinestatic

Definition at line 1827 of file dl_rendering_unittests.cc.

1827 {
1828 std::string base_dir = "./failure_images";
1829 if (CheckDir(base_dir) == DirectoryStatus::kFailed) {
1830 return;
1831 }
1832 for (int i = 0; i < 10000; i++) {
1833 std::string sub_dir = std::to_string(i);
1834 while (sub_dir.length() < 4) {
1835 sub_dir = "0" + sub_dir;
1836 }
1837 std::string try_dir = base_dir + "/" + sub_dir;
1838 switch (CheckDir(try_dir)) {
1840 break;
1842 failure_image_directory_ = try_dir;
1843 return;
1845 return;
1846 }
1847 }
1848 FML_LOG(ERROR) << "Too many output directories for failure images";
1849 }
static DirectoryStatus CheckDir(const std::string &dir)

References CheckDir(), FML_LOG, i, kCreated, kExisted, and kFailed.

Referenced by save_to_png().

◆ showBoundsOverflow()

static void flutter::testing::CanvasCompareTester::showBoundsOverflow ( const std::string &  info,
DlIRect bounds,
const BoundsTolerance tolerance,
int  pixLeft,
int  pixTop,
int  pixRight,
int  pixBottom 
)
inlinestatic

Definition at line 2212 of file dl_rendering_unittests.cc.

2218 {
2219 int pad_left = std::max(0, pixLeft - bounds.GetLeft());
2220 int pad_top = std::max(0, pixTop - bounds.GetTop());
2221 int pad_right = std::max(0, bounds.GetRight() - pixRight);
2222 int pad_bottom = std::max(0, bounds.GetBottom() - pixBottom);
2223 DlIRect pix_bounds =
2224 DlIRect::MakeLTRB(pixLeft, pixTop, pixRight, pixBottom);
2225 DlISize pix_size = pix_bounds.GetSize();
2226 int pix_width = pix_size.width;
2227 int pix_height = pix_size.height;
2228 int worst_pad_x = std::max(pad_left, pad_right);
2229 int worst_pad_y = std::max(pad_top, pad_bottom);
2230 if (tolerance->overflows(pix_bounds, worst_pad_x, worst_pad_y)) {
2231 FML_LOG(ERROR) << "Computed bounds for " << info;
2232 FML_LOG(ERROR) << "pix bounds[" //
2233 << pixLeft << ", " << pixTop << " => " //
2234 << pixRight << ", " << pixBottom //
2235 << "]";
2236 FML_LOG(ERROR) << "dl_bounds[" << bounds << "]";
2237 FML_LOG(ERROR) << "Bounds overly conservative by up to " //
2238 << worst_pad_x << ", " << worst_pad_y //
2239 << " (" << (worst_pad_x * 100.0 / pix_width) //
2240 << "%, " << (worst_pad_y * 100.0 / pix_height) << "%)";
2241 int pix_area = pix_size.Area();
2242 int dl_area = bounds.Area();
2243 FML_LOG(ERROR) << "Total overflow area: " << (dl_area - pix_area) //
2244 << " (+" << (dl_area * 100.0 / pix_area - 100.0) //
2245 << "% larger)";
2246 FML_LOG(ERROR);
2247 }
2248 }
impeller::ISize32 DlISize
Type width
Definition size.h:28

References impeller::TRect< T >::Area(), impeller::TSize< T >::Area(), FML_LOG, impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::TSize< T >::height, impeller::TRect< T >::MakeLTRB(), flutter::testing::BoundsTolerance::overflows(), and impeller::TSize< T >::width.

Referenced by compareToReference().

Member Data Documentation

◆ DefaultTolerance

BoundsTolerance flutter::testing::CanvasCompareTester::DefaultTolerance
static
Initial value:
=
BoundsTolerance().addAbsolutePadding(1, 1)

Definition at line 930 of file dl_rendering_unittests.cc.

Referenced by flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().


The documentation for this class was generated from the following file: