static void RenderWithAttributes()

in display_list/display_list_canvas_unittests.cc [897:1278]


  static void RenderWithAttributes(const TestParameters& testP,
                                   const RenderEnvironment& env,
                                   const BoundsTolerance& tolerance) {
    RenderWith(testP, env, tolerance, CaseParameters("Defaults Test"));

    {
      // CPU renderer with default line width of 0 does not show antialiasing
      // for stroked primitives, so we make a new reference with a non-trivial
      // stroke width to demonstrate the differences
      RenderEnvironment aa_env = RenderEnvironment::MakeN32();
      // Tweak the bounds tolerance for the displacement of 1/10 of a pixel
      const BoundsTolerance aa_tolerance = tolerance.addBoundsPadding(1, 1);
      CvSetup cv_aa_setup = [=](SkCanvas* cv, SkPaint& p) {
        cv->translate(0.1, 0.1);
        p.setStrokeWidth(5.0);
      };
      DlRenderer dl_aa_setup = [=](DisplayListBuilder& b) {
        b.translate(0.1, 0.1);
        b.setStrokeWidth(5.0);
      };
      aa_env.init_ref(cv_aa_setup, testP.cv_renderer());
      RenderWith(testP, aa_env, aa_tolerance,
                 CaseParameters(
                     "AntiAlias == True",
                     [=](SkCanvas* cv, SkPaint& p) {
                       cv_aa_setup(cv, p);
                       p.setAntiAlias(true);
                     },
                     [=](DisplayListBuilder& b) {
                       dl_aa_setup(b);
                       b.setAntiAlias(true);
                     }));
      RenderWith(testP, aa_env, aa_tolerance,
                 CaseParameters(
                     "AntiAlias == False",
                     [=](SkCanvas* cv, SkPaint& p) {
                       cv_aa_setup(cv, p);
                       p.setAntiAlias(false);
                     },
                     [=](DisplayListBuilder& b) {
                       dl_aa_setup(b);
                       b.setAntiAlias(false);
                     }));
    }

    {
      // The CPU renderer does not always dither for solid colors and we
      // need to use a non-default color (default is black) on an opaque
      // surface, so we use a shader instead of a color. Also, thin stroked
      // primitives (mainly drawLine and drawPoints) do not show much
      // dithering so we use a non-trivial stroke width as well.
      RenderEnvironment dither_env = RenderEnvironment::Make565();
      SkColor dither_bg = SK_ColorBLACK;
      CvSetup cv_dither_setup = [=](SkCanvas*, SkPaint& p) {
        p.setShader(testImageShader);
        p.setAlpha(0xf0);
        p.setStrokeWidth(5.0);
      };
      DlRenderer dl_dither_setup = [=](DisplayListBuilder& b) {
        b.setShader(testImageShader);
        b.setColor(SkColor(0xf0000000));
        b.setStrokeWidth(5.0);
      };
      dither_env.init_ref(cv_dither_setup, testP.cv_renderer(), dither_bg);
      RenderWith(testP, dither_env, tolerance,
                 CaseParameters(
                     "Dither == True",
                     [=](SkCanvas* cv, SkPaint& p) {
                       cv_dither_setup(cv, p);
                       p.setDither(true);
                     },
                     [=](DisplayListBuilder& b) {
                       dl_dither_setup(b);
                       b.setDither(true);
                     })
                     .with_bg(dither_bg));
      RenderWith(testP, dither_env, tolerance,
                 CaseParameters(
                     "Dither = False",
                     [=](SkCanvas* cv, SkPaint& p) {
                       cv_dither_setup(cv, p);
                       p.setDither(false);
                     },
                     [=](DisplayListBuilder& b) {
                       dl_dither_setup(b);
                       b.setDither(false);
                     })
                     .with_bg(dither_bg));
    }
    EXPECT_TRUE(testImageShader->unique()) << "Dither Cleanup";

    RenderWith(testP, env, tolerance,
               CaseParameters(
                   "Color == Blue",
                   [=](SkCanvas*, SkPaint& p) { p.setColor(SK_ColorBLUE); },
                   [=](DisplayListBuilder& b) { b.setColor(SK_ColorBLUE); }));
    RenderWith(testP, env, tolerance,
               CaseParameters(
                   "Color == Green",
                   [=](SkCanvas*, SkPaint& p) { p.setColor(SK_ColorGREEN); },
                   [=](DisplayListBuilder& b) { b.setColor(SK_ColorGREEN); }));

    RenderWithStrokes(testP, env, tolerance);

    {
      // half opaque cyan
      SkColor blendableColor = SkColorSetARGB(0x7f, 0x00, 0xff, 0xff);
      SkColor bg = SK_ColorWHITE;

      RenderWith(testP, env, tolerance,
                 CaseParameters(
                     "Blend == SrcIn",
                     [=](SkCanvas*, SkPaint& p) {
                       p.setBlendMode(SkBlendMode::kSrcIn);
                       p.setColor(blendableColor);
                     },
                     [=](DisplayListBuilder& b) {
                       b.setBlendMode(SkBlendMode::kSrcIn);
                       b.setColor(blendableColor);
                     })
                     .with_bg(bg));
      RenderWith(testP, env, tolerance,
                 CaseParameters(
                     "Blend == DstIn",
                     [=](SkCanvas*, SkPaint& p) {
                       p.setBlendMode(SkBlendMode::kDstIn);
                       p.setColor(blendableColor);
                     },
                     [=](DisplayListBuilder& b) {
                       b.setBlendMode(SkBlendMode::kDstIn);
                       b.setColor(blendableColor);
                     })
                     .with_bg(bg));
    }

    if (!(testP.is_draw_atlas() || testP.is_draw_vertices())) {
      sk_sp<SkBlender> blender =
          SkBlenders::Arithmetic(0.25, 0.25, 0.25, 0.25, false);
      {
        RenderWith(testP, env, tolerance,
                   CaseParameters(
                       "Blender == Arithmetic 0.25-false",
                       [=](SkCanvas*, SkPaint& p) { p.setBlender(blender); },
                       [=](DisplayListBuilder& b) { b.setBlender(blender); }));
      }
      EXPECT_TRUE(blender->unique()) << "Blender Cleanup";
      blender = SkBlenders::Arithmetic(0.25, 0.25, 0.25, 0.25, true);
      {
        RenderWith(testP, env, tolerance,
                   CaseParameters(
                       "Blender == Arithmetic 0.25-true",
                       [=](SkCanvas*, SkPaint& p) { p.setBlender(blender); },
                       [=](DisplayListBuilder& b) { b.setBlender(blender); }));
      }
      EXPECT_TRUE(blender->unique()) << "Blender Cleanup";
    }

    {
      // Being able to see a blur requires some non-default attributes,
      // like a non-trivial stroke width and a shader rather than a color
      // (for drawPaint) so we create a new environment for these tests.
      RenderEnvironment blur_env = RenderEnvironment::MakeN32();
      CvSetup cv_blur_setup = [=](SkCanvas*, SkPaint& p) {
        p.setShader(testImageShader);
        p.setStrokeWidth(5.0);
      };
      DlRenderer dl_blur_setup = [=](DisplayListBuilder& b) {
        b.setShader(testImageShader);
        b.setStrokeWidth(5.0);
      };
      blur_env.init_ref(cv_blur_setup, testP.cv_renderer());
      sk_sp<SkImageFilter> filter =
          SkImageFilters::Blur(5.0, 5.0, SkTileMode::kDecal, nullptr, nullptr);
      BoundsTolerance blur5Tolerance = tolerance.addBoundsPadding(4, 4);
      {
        RenderWith(testP, blur_env, blur5Tolerance,
                   CaseParameters(
                       "ImageFilter == Decal Blur 5",
                       [=](SkCanvas* cv, SkPaint& p) {
                         cv_blur_setup(cv, p);
                         p.setImageFilter(filter);
                       },
                       [=](DisplayListBuilder& b) {
                         dl_blur_setup(b);
                         b.setImageFilter(filter);
                       }));
      }
      EXPECT_TRUE(filter->unique()) << "ImageFilter Cleanup";
      filter =
          SkImageFilters::Blur(5.0, 5.0, SkTileMode::kClamp, nullptr, nullptr);
      {
        RenderWith(testP, blur_env, blur5Tolerance,
                   CaseParameters(
                       "ImageFilter == Clamp Blur 5",
                       [=](SkCanvas* cv, SkPaint& p) {
                         cv_blur_setup(cv, p);
                         p.setImageFilter(filter);
                       },
                       [=](DisplayListBuilder& b) {
                         dl_blur_setup(b);
                         b.setImageFilter(filter);
                       }));
      }
      EXPECT_TRUE(filter->unique()) << "ImageFilter Cleanup";
    }

    {
      // clang-format off
      constexpr float rotate_color_matrix[20] = {
          0, 1, 0, 0, 0,
          0, 0, 1, 0, 0,
          1, 0, 0, 0, 0,
          0, 0, 0, 1, 0,
      };
      constexpr float invert_color_matrix[20] = {
        -1.0,    0,    0, 1.0,   0,
           0, -1.0,    0, 1.0,   0,
           0,    0, -1.0, 1.0,   0,
         1.0,  1.0,  1.0, 1.0,   0,
      };
      // clang-format on
      sk_sp<SkColorFilter> filter = SkColorFilters::Matrix(rotate_color_matrix);
      {
        SkColor bg = SK_ColorWHITE;
        RenderWith(testP, env, tolerance,
                   CaseParameters(
                       "ColorFilter == RotateRGB",
                       [=](SkCanvas*, SkPaint& p) {
                         p.setColor(SK_ColorYELLOW);
                         p.setColorFilter(filter);
                       },
                       [=](DisplayListBuilder& b) {
                         b.setColor(SK_ColorYELLOW);
                         b.setColorFilter(filter);
                       })
                       .with_bg(bg));
      }
      EXPECT_TRUE(filter->unique()) << "ColorFilter == RotateRGB Cleanup";
      filter = SkColorFilters::Matrix(invert_color_matrix);
      {
        SkColor bg = SK_ColorWHITE;
        RenderWith(testP, env, tolerance,
                   CaseParameters(
                       "ColorFilter == Invert",
                       [=](SkCanvas*, SkPaint& p) {
                         p.setColor(SK_ColorYELLOW);
                         p.setColorFilter(filter);
                       },
                       [=](DisplayListBuilder& b) {
                         b.setColor(SK_ColorYELLOW);
                         b.setInvertColors(true);
                       })
                       .with_bg(bg));
      }
      EXPECT_TRUE(filter->unique()) << "ColorFilter == Invert Cleanup";
    }

    {
      sk_sp<SkPathEffect> effect = SkDiscretePathEffect::Make(3, 5);
      {
        // Discrete path effects need a stroke width for drawPointsAsPoints
        // to do something realistic
        // And a Discrete(3, 5) effect produces miters that are near
        // maximal for a miter limit of 3.0.
        BoundsTolerance discrete_tolerance =
            tolerance
                // register the discrete offset so adjusters can compensate
                .addDiscreteOffset(5)
                // the miters in the 3-5 discrete effect don't always fill
                // their conservative bounds, so tolerate a couple of pixels
                .addBoundsPadding(2, 2);
        RenderWith(testP, env, discrete_tolerance,
                   CaseParameters(
                       "PathEffect == Discrete-3-5",
                       [=](SkCanvas*, SkPaint& p) {
                         p.setStrokeWidth(5.0);
                         p.setStrokeMiter(3.0);
                         p.setPathEffect(effect);
                       },
                       [=](DisplayListBuilder& b) {
                         b.setStrokeWidth(5.0);
                         b.setStrokeMiter(3.0);
                         b.setPathEffect(effect);
                       }));
      }
      EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique())
          << "PathEffect == Discrete-3-5 Cleanup";
      effect = SkDiscretePathEffect::Make(2, 3);
      {
        // Discrete path effects need a stroke width for drawPointsAsPoints
        // to do something realistic
        // And a Discrete(2, 3) effect produces miters that are near
        // maximal for a miter limit of 2.5.
        BoundsTolerance discrete_tolerance =
            tolerance
                // register the discrete offset so adjusters can compensate
                .addDiscreteOffset(3)
                // the miters in the 3-5 discrete effect don't always fill
                // their conservative bounds, so tolerate a couple of pixels
                .addBoundsPadding(2, 2);
        RenderWith(testP, env, discrete_tolerance,
                   CaseParameters(
                       "PathEffect == Discrete-2-3",
                       [=](SkCanvas*, SkPaint& p) {
                         p.setStrokeWidth(5.0);
                         p.setStrokeMiter(2.5);
                         p.setPathEffect(effect);
                       },
                       [=](DisplayListBuilder& b) {
                         b.setStrokeWidth(5.0);
                         b.setStrokeMiter(2.5);
                         b.setPathEffect(effect);
                       }));
      }
      EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique())
          << "PathEffect == Discrete-2-3 Cleanup";
    }

    {
      sk_sp<SkMaskFilter> filter =
          SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5.0);
      BoundsTolerance blur5Tolerance = tolerance.addBoundsPadding(4, 4);
      {
        // Stroked primitives need some non-trivial stroke size to be blurred
        RenderWith(testP, env, blur5Tolerance,
                   CaseParameters(
                       "MaskFilter == Blur 5",
                       [=](SkCanvas*, SkPaint& p) {
                         p.setStrokeWidth(5.0);
                         p.setMaskFilter(filter);
                       },
                       [=](DisplayListBuilder& b) {
                         b.setStrokeWidth(5.0);
                         b.setMaskFilter(filter);
                       }));
      }
      EXPECT_TRUE(testP.is_draw_text_blob() || filter->unique())
          << "MaskFilter == Blur 5 Cleanup";
      {
        RenderWith(testP, env, blur5Tolerance,
                   CaseParameters(
                       "MaskFilter == Blur(Normal, 5.0)",
                       [=](SkCanvas*, SkPaint& p) {
                         p.setStrokeWidth(5.0);
                         p.setMaskFilter(filter);
                       },
                       [=](DisplayListBuilder& b) {
                         b.setStrokeWidth(5.0);
                         b.setMaskBlurFilter(kNormal_SkBlurStyle, 5.0);
                       }));
      }
      EXPECT_TRUE(testP.is_draw_text_blob() || filter->unique())
          << "MaskFilter == Blur(Normal, 5.0) Cleanup";
    }

    {
      SkPoint end_points[] = {
          SkPoint::Make(RenderBounds.fLeft, RenderBounds.fTop),
          SkPoint::Make(RenderBounds.fRight, RenderBounds.fBottom),
      };
      SkColor colors[] = {
          SK_ColorGREEN,
          SkColorSetA(SK_ColorYELLOW, 0x7f),
          SK_ColorBLUE,
      };
      float stops[] = {
          0.0,
          0.5,
          1.0,
      };
      sk_sp<SkShader> shader = SkGradientShader::MakeLinear(
          end_points, colors, stops, 3, SkTileMode::kMirror, 0, nullptr);
      {
        RenderWith(testP, env, tolerance,
                   CaseParameters(
                       "LinearGradient GYB",
                       [=](SkCanvas*, SkPaint& p) { p.setShader(shader); },
                       [=](DisplayListBuilder& b) { b.setShader(shader); }));
      }
      EXPECT_TRUE(shader->unique()) << "LinearGradient GYB Cleanup";
    }
  }