// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/display_list/dl_dispatcher.h"

#include <algorithm>
#include <cstring>
#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "impeller/aiks/color_filter.h"
#include "impeller/core/formats.h"
#include "impeller/display_list/dl_vertices_geometry.h"
#include "impeller/display_list/nine_patch_converter.h"
#include "impeller/display_list/skia_conversions.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/runtime_effect_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/sigma.h"

#if IMPELLER_ENABLE_3D
#include "impeller/entity/contents/scene_contents.h"
#endif  // IMPELLER_ENABLE_3D

namespace impeller {

#define UNIMPLEMENTED \
  FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;

static BlendMode ToBlendMode(flutter::DlBlendMode mode) {
  switch (mode) {
    case flutter::DlBlendMode::kClear:
      return BlendMode::kClear;
    case flutter::DlBlendMode::kSrc:
      return BlendMode::kSource;
    case flutter::DlBlendMode::kDst:
      return BlendMode::kDestination;
    case flutter::DlBlendMode::kSrcOver:
      return BlendMode::kSourceOver;
    case flutter::DlBlendMode::kDstOver:
      return BlendMode::kDestinationOver;
    case flutter::DlBlendMode::kSrcIn:
      return BlendMode::kSourceIn;
    case flutter::DlBlendMode::kDstIn:
      return BlendMode::kDestinationIn;
    case flutter::DlBlendMode::kSrcOut:
      return BlendMode::kSourceOut;
    case flutter::DlBlendMode::kDstOut:
      return BlendMode::kDestinationOut;
    case flutter::DlBlendMode::kSrcATop:
      return BlendMode::kSourceATop;
    case flutter::DlBlendMode::kDstATop:
      return BlendMode::kDestinationATop;
    case flutter::DlBlendMode::kXor:
      return BlendMode::kXor;
    case flutter::DlBlendMode::kPlus:
      return BlendMode::kPlus;
    case flutter::DlBlendMode::kModulate:
      return BlendMode::kModulate;
    case flutter::DlBlendMode::kScreen:
      return BlendMode::kScreen;
    case flutter::DlBlendMode::kOverlay:
      return BlendMode::kOverlay;
    case flutter::DlBlendMode::kDarken:
      return BlendMode::kDarken;
    case flutter::DlBlendMode::kLighten:
      return BlendMode::kLighten;
    case flutter::DlBlendMode::kColorDodge:
      return BlendMode::kColorDodge;
    case flutter::DlBlendMode::kColorBurn:
      return BlendMode::kColorBurn;
    case flutter::DlBlendMode::kHardLight:
      return BlendMode::kHardLight;
    case flutter::DlBlendMode::kSoftLight:
      return BlendMode::kSoftLight;
    case flutter::DlBlendMode::kDifference:
      return BlendMode::kDifference;
    case flutter::DlBlendMode::kExclusion:
      return BlendMode::kExclusion;
    case flutter::DlBlendMode::kMultiply:
      return BlendMode::kMultiply;
    case flutter::DlBlendMode::kHue:
      return BlendMode::kHue;
    case flutter::DlBlendMode::kSaturation:
      return BlendMode::kSaturation;
    case flutter::DlBlendMode::kColor:
      return BlendMode::kColor;
    case flutter::DlBlendMode::kLuminosity:
      return BlendMode::kLuminosity;
  }
  FML_UNREACHABLE();
}

static Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) {
  switch (tile_mode) {
    case flutter::DlTileMode::kClamp:
      return Entity::TileMode::kClamp;
    case flutter::DlTileMode::kRepeat:
      return Entity::TileMode::kRepeat;
    case flutter::DlTileMode::kMirror:
      return Entity::TileMode::kMirror;
    case flutter::DlTileMode::kDecal:
      return Entity::TileMode::kDecal;
  }
}

static impeller::SamplerDescriptor ToSamplerDescriptor(
    const flutter::DlImageSampling options) {
  impeller::SamplerDescriptor desc;
  switch (options) {
    case flutter::DlImageSampling::kNearestNeighbor:
      desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
      desc.label = "Nearest Sampler";
      break;
    case flutter::DlImageSampling::kLinear:
    // Impeller doesn't support cubic sampling, but linear is closer to correct
    // than nearest for this case.
    case flutter::DlImageSampling::kCubic:
      desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
      desc.label = "Linear Sampler";
      break;
    case flutter::DlImageSampling::kMipmapLinear:
      desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
      desc.mip_filter = impeller::MipFilter::kLinear;
      desc.label = "Mipmap Linear Sampler";
      break;
  }
  return desc;
}

static impeller::SamplerDescriptor ToSamplerDescriptor(
    const flutter::DlFilterMode options) {
  impeller::SamplerDescriptor desc;
  switch (options) {
    case flutter::DlFilterMode::kNearest:
      desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
      desc.label = "Nearest Sampler";
      break;
    case flutter::DlFilterMode::kLinear:
      desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
      desc.label = "Linear Sampler";
      break;
    default:
      break;
  }
  return desc;
}

static Matrix ToMatrix(const SkMatrix& m) {
  return Matrix{
      // clang-format off
      m[0], m[3], 0, m[6],
      m[1], m[4], 0, m[7],
      0,    0,    1, 0,
      m[2], m[5], 0, m[8],
      // clang-format on
  };
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setAntiAlias(bool aa) {
  // Nothing to do because AA is implicit.
}

static Paint::Style ToStyle(flutter::DlDrawStyle style) {
  switch (style) {
    case flutter::DlDrawStyle::kFill:
      return Paint::Style::kFill;
    case flutter::DlDrawStyle::kStroke:
      return Paint::Style::kStroke;
    case flutter::DlDrawStyle::kStrokeAndFill:
      UNIMPLEMENTED;
      break;
  }
  return Paint::Style::kFill;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setDrawStyle(flutter::DlDrawStyle style) {
  paint_.style = ToStyle(style);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setColor(flutter::DlColor color) {
  paint_.color = {
      color.getRedF(),
      color.getGreenF(),
      color.getBlueF(),
      color.getAlphaF(),
  };
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setStrokeWidth(SkScalar width) {
  paint_.stroke_width = width;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setStrokeMiter(SkScalar limit) {
  paint_.stroke_miter = limit;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setStrokeCap(flutter::DlStrokeCap cap) {
  switch (cap) {
    case flutter::DlStrokeCap::kButt:
      paint_.stroke_cap = Cap::kButt;
      break;
    case flutter::DlStrokeCap::kRound:
      paint_.stroke_cap = Cap::kRound;
      break;
    case flutter::DlStrokeCap::kSquare:
      paint_.stroke_cap = Cap::kSquare;
      break;
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setStrokeJoin(flutter::DlStrokeJoin join) {
  switch (join) {
    case flutter::DlStrokeJoin::kMiter:
      paint_.stroke_join = Join::kMiter;
      break;
    case flutter::DlStrokeJoin::kRound:
      paint_.stroke_join = Join::kRound;
      break;
    case flutter::DlStrokeJoin::kBevel:
      paint_.stroke_join = Join::kBevel;
      break;
  }
}

static std::vector<Color> ToColors(const flutter::DlColor colors[], int count) {
  auto result = std::vector<Color>();
  if (colors == nullptr) {
    return result;
  }
  for (int i = 0; i < count; i++) {
    result.push_back(skia_conversions::ToColor(colors[i]));
  }
  return result;
}

static std::optional<ColorSource::Type> ToColorSourceType(
    flutter::DlColorSourceType type) {
  switch (type) {
    case flutter::DlColorSourceType::kColor:
      return ColorSource::Type::kColor;
    case flutter::DlColorSourceType::kImage:
      return ColorSource::Type::kImage;
    case flutter::DlColorSourceType::kLinearGradient:
      return ColorSource::Type::kLinearGradient;
    case flutter::DlColorSourceType::kRadialGradient:
      return ColorSource::Type::kRadialGradient;
    case flutter::DlColorSourceType::kConicalGradient:
      return ColorSource::Type::kConicalGradient;
    case flutter::DlColorSourceType::kSweepGradient:
      return ColorSource::Type::kSweepGradient;
    case flutter::DlColorSourceType::kRuntimeEffect:
      return ColorSource::Type::kRuntimeEffect;
#ifdef IMPELLER_ENABLE_3D
    case flutter::DlColorSourceType::kScene:
      return ColorSource::Type::kScene;
#endif  // IMPELLER_ENABLE_3D
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setColorSource(const flutter::DlColorSource* source) {
  if (!source) {
    paint_.color_source = ColorSource::MakeColor();
    return;
  }

  std::optional<ColorSource::Type> type = ToColorSourceType(source->type());

  if (!type.has_value()) {
    FML_LOG(ERROR) << "Requested ColorSourceType::kUnknown";
    paint_.color_source = ColorSource::MakeColor();
    return;
  }

  switch (type.value()) {
    case ColorSource::Type::kColor: {
      const flutter::DlColorColorSource* color = source->asColor();

      paint_.color_source = ColorSource::MakeColor();
      setColor(color->color());
      FML_DCHECK(color);
      return;
    }
    case ColorSource::Type::kLinearGradient: {
      const flutter::DlLinearGradientColorSource* linear =
          source->asLinearGradient();
      FML_DCHECK(linear);
      auto start_point = skia_conversions::ToPoint(linear->start_point());
      auto end_point = skia_conversions::ToPoint(linear->end_point());
      std::vector<Color> colors;
      std::vector<float> stops;
      skia_conversions::ConvertStops(linear, colors, stops);

      auto tile_mode = ToTileMode(linear->tile_mode());
      auto matrix = ToMatrix(linear->matrix());

      paint_.color_source = ColorSource::MakeLinearGradient(
          start_point, end_point, std::move(colors), std::move(stops),
          tile_mode, matrix);
      return;
    }
    case ColorSource::Type::kConicalGradient: {
      const flutter::DlConicalGradientColorSource* conical_gradient =
          source->asConicalGradient();
      FML_DCHECK(conical_gradient);
      Point center = skia_conversions::ToPoint(conical_gradient->end_center());
      SkScalar radius = conical_gradient->end_radius();
      Point focus_center =
          skia_conversions::ToPoint(conical_gradient->start_center());
      SkScalar focus_radius = conical_gradient->start_radius();
      std::vector<Color> colors;
      std::vector<float> stops;
      skia_conversions::ConvertStops(conical_gradient, colors, stops);

      auto tile_mode = ToTileMode(conical_gradient->tile_mode());
      auto matrix = ToMatrix(conical_gradient->matrix());

      paint_.color_source = ColorSource::MakeConicalGradient(
          center, radius, std::move(colors), std::move(stops), focus_center,
          focus_radius, tile_mode, matrix);
      return;
    }
    case ColorSource::Type::kRadialGradient: {
      const flutter::DlRadialGradientColorSource* radialGradient =
          source->asRadialGradient();
      FML_DCHECK(radialGradient);
      auto center = skia_conversions::ToPoint(radialGradient->center());
      auto radius = radialGradient->radius();
      std::vector<Color> colors;
      std::vector<float> stops;
      skia_conversions::ConvertStops(radialGradient, colors, stops);

      auto tile_mode = ToTileMode(radialGradient->tile_mode());
      auto matrix = ToMatrix(radialGradient->matrix());
      paint_.color_source =
          ColorSource::MakeRadialGradient(center, radius, std::move(colors),
                                          std::move(stops), tile_mode, matrix);
      return;
    }
    case ColorSource::Type::kSweepGradient: {
      const flutter::DlSweepGradientColorSource* sweepGradient =
          source->asSweepGradient();
      FML_DCHECK(sweepGradient);

      auto center = skia_conversions::ToPoint(sweepGradient->center());
      auto start_angle = Degrees(sweepGradient->start());
      auto end_angle = Degrees(sweepGradient->end());
      std::vector<Color> colors;
      std::vector<float> stops;
      skia_conversions::ConvertStops(sweepGradient, colors, stops);

      auto tile_mode = ToTileMode(sweepGradient->tile_mode());
      auto matrix = ToMatrix(sweepGradient->matrix());
      paint_.color_source = ColorSource::MakeSweepGradient(
          center, start_angle, end_angle, std::move(colors), std::move(stops),
          tile_mode, matrix);
      return;
    }
    case ColorSource::Type::kImage: {
      const flutter::DlImageColorSource* image_color_source = source->asImage();
      FML_DCHECK(image_color_source &&
                 image_color_source->image()->impeller_texture());
      auto texture = image_color_source->image()->impeller_texture();
      auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode());
      auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode());
      auto desc = ToSamplerDescriptor(image_color_source->sampling());
      auto matrix = ToMatrix(image_color_source->matrix());
      paint_.color_source = ColorSource::MakeImage(texture, x_tile_mode,
                                                   y_tile_mode, desc, matrix);
      return;
    }
    case ColorSource::Type::kRuntimeEffect: {
      const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
          source->asRuntimeEffect();
      auto runtime_stage =
          runtime_effect_color_source->runtime_effect()->runtime_stage();
      auto uniform_data = runtime_effect_color_source->uniform_data();
      auto samplers = runtime_effect_color_source->samplers();

      std::vector<RuntimeEffectContents::TextureInput> texture_inputs;

      for (auto& sampler : samplers) {
        if (sampler == nullptr) {
          return;
        }
        auto* image = sampler->asImage();
        if (!sampler->asImage()) {
          UNIMPLEMENTED;
          return;
        }
        FML_DCHECK(image->image()->impeller_texture());
        texture_inputs.push_back({
            .sampler_descriptor = ToSamplerDescriptor(image->sampling()),
            .texture = image->image()->impeller_texture(),
        });
      }

      paint_.color_source = ColorSource::MakeRuntimeEffect(
          runtime_stage, uniform_data, texture_inputs);
      return;
    }
    case ColorSource::Type::kScene: {
#ifdef IMPELLER_ENABLE_3D
      const flutter::DlSceneColorSource* scene_color_source = source->asScene();
      std::shared_ptr<scene::Node> scene_node =
          scene_color_source->scene_node();
      Matrix camera_transform = scene_color_source->camera_matrix();

      paint_.color_source =
          ColorSource::MakeScene(scene_node, camera_transform);
#else   // IMPELLER_ENABLE_3D
      FML_LOG(ERROR) << "ColorSourceType::kScene can only be used if Impeller "
                        "Scene is enabled.";
#endif  // IMPELLER_ENABLE_3D
      return;
    }
  }
}

static std::shared_ptr<ColorFilter> ToColorFilter(
    const flutter::DlColorFilter* filter) {
  if (filter == nullptr) {
    return nullptr;
  }
  switch (filter->type()) {
    case flutter::DlColorFilterType::kBlend: {
      auto dl_blend = filter->asBlend();
      auto blend_mode = ToBlendMode(dl_blend->mode());
      auto color = skia_conversions::ToColor(dl_blend->color());
      return ColorFilter::MakeBlend(blend_mode, color);
    }
    case flutter::DlColorFilterType::kMatrix: {
      const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix();
      impeller::ColorMatrix color_matrix;
      dl_matrix->get_matrix(color_matrix.array);
      return ColorFilter::MakeMatrix(color_matrix);
    }
    case flutter::DlColorFilterType::kSrgbToLinearGamma:
      return ColorFilter::MakeSrgbToLinear();
    case flutter::DlColorFilterType::kLinearToSrgbGamma:
      return ColorFilter::MakeLinearToSrgb();
  }
  return nullptr;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setColorFilter(const flutter::DlColorFilter* filter) {
  paint_.color_filter = ToColorFilter(filter);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setInvertColors(bool invert) {
  paint_.invert_colors = invert;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setBlendMode(flutter::DlBlendMode dl_mode) {
  paint_.blend_mode = ToBlendMode(dl_mode);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setPathEffect(const flutter::DlPathEffect* effect) {
  // Needs https://github.com/flutter/flutter/issues/95434
  UNIMPLEMENTED;
}

static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style) {
  switch (blur_style) {
    case flutter::DlBlurStyle::kNormal:
      return FilterContents::BlurStyle::kNormal;
    case flutter::DlBlurStyle::kSolid:
      return FilterContents::BlurStyle::kSolid;
    case flutter::DlBlurStyle::kOuter:
      return FilterContents::BlurStyle::kOuter;
    case flutter::DlBlurStyle::kInner:
      return FilterContents::BlurStyle::kInner;
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setMaskFilter(const flutter::DlMaskFilter* filter) {
  // Needs https://github.com/flutter/flutter/issues/95434
  if (filter == nullptr) {
    paint_.mask_blur_descriptor = std::nullopt;
    return;
  }
  switch (filter->type()) {
    case flutter::DlMaskFilterType::kBlur: {
      auto blur = filter->asBlur();

      paint_.mask_blur_descriptor = {
          .style = ToBlurStyle(blur->style()),
          .sigma = Sigma(blur->sigma()),
      };
      break;
    }
  }
}

static std::shared_ptr<ImageFilter> ToImageFilter(
    const flutter::DlImageFilter* filter) {
  if (filter == nullptr) {
    return nullptr;
  }

  switch (filter->type()) {
    case flutter::DlImageFilterType::kBlur: {
      auto blur = filter->asBlur();
      auto sigma_x = Sigma(blur->sigma_x());
      auto sigma_y = Sigma(blur->sigma_y());
      auto tile_mode = ToTileMode(blur->tile_mode());
      return ImageFilter::MakeBlur(
          sigma_x, sigma_y, FilterContents::BlurStyle::kNormal, tile_mode);
    }
    case flutter::DlImageFilterType::kDilate: {
      auto dilate = filter->asDilate();
      FML_DCHECK(dilate);
      if (dilate->radius_x() < 0 || dilate->radius_y() < 0) {
        return nullptr;
      }
      auto radius_x = Radius(dilate->radius_x());
      auto radius_y = Radius(dilate->radius_y());
      return ImageFilter::MakeDilate(radius_x, radius_y);
    }
    case flutter::DlImageFilterType::kErode: {
      auto erode = filter->asErode();
      FML_DCHECK(erode);
      if (erode->radius_x() < 0 || erode->radius_y() < 0) {
        return nullptr;
      }
      auto radius_x = Radius(erode->radius_x());
      auto radius_y = Radius(erode->radius_y());
      return ImageFilter::MakeErode(radius_x, radius_y);
    }
    case flutter::DlImageFilterType::kMatrix: {
      auto matrix_filter = filter->asMatrix();
      FML_DCHECK(matrix_filter);
      auto matrix = ToMatrix(matrix_filter->matrix());
      auto desc = ToSamplerDescriptor(matrix_filter->sampling());
      return ImageFilter::MakeMatrix(matrix, desc);
    }
    case flutter::DlImageFilterType::kCompose: {
      auto compose = filter->asCompose();
      FML_DCHECK(compose);
      auto outer_dl_filter = compose->outer();
      auto inner_dl_filter = compose->inner();
      auto outer_filter = ToImageFilter(outer_dl_filter.get());
      auto inner_filter = ToImageFilter(inner_dl_filter.get());
      if (!outer_filter) {
        return inner_filter;
      }
      if (!inner_filter) {
        return outer_filter;
      }
      FML_DCHECK(outer_filter && inner_filter);

      return ImageFilter::MakeCompose(*inner_filter, *outer_filter);
    }
    case flutter::DlImageFilterType::kColorFilter: {
      auto color_filter_image_filter = filter->asColorFilter();
      FML_DCHECK(color_filter_image_filter);
      auto color_filter =
          ToColorFilter(color_filter_image_filter->color_filter().get());
      if (!color_filter) {
        return nullptr;
      }
      // When color filters are used as image filters, set the color filter's
      // "absorb opacity" flag to false. For image filters, the snapshot
      // opacity needs to be deferred until the result of the filter chain is
      // being blended with the layer.
      return ImageFilter::MakeFromColorFilter(*color_filter);
    }
    case flutter::DlImageFilterType::kLocalMatrix: {
      auto local_matrix_filter = filter->asLocalMatrix();
      FML_DCHECK(local_matrix_filter);
      auto internal_filter = local_matrix_filter->image_filter();
      FML_DCHECK(internal_filter);

      auto image_filter = ToImageFilter(internal_filter.get());
      if (!image_filter) {
        return nullptr;
      }

      auto matrix = ToMatrix(local_matrix_filter->matrix());
      return ImageFilter::MakeLocalMatrix(matrix, *image_filter);
    }
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::setImageFilter(const flutter::DlImageFilter* filter) {
  paint_.image_filter = ToImageFilter(filter);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::save(uint32_t total_content_depth) {
  GetCanvas().Save(total_content_depth);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::saveLayer(const SkRect& bounds,
                                 const flutter::SaveLayerOptions& options,
                                 uint32_t total_content_depth,
                                 const flutter::DlImageFilter* backdrop) {
  auto paint = options.renders_with_attributes() ? paint_ : Paint{};
  auto promise = options.content_is_clipped()
                     ? ContentBoundsPromise::kMayClipContents
                     : ContentBoundsPromise::kContainsContents;
  GetCanvas().SaveLayer(paint, skia_conversions::ToRect(bounds),
                        ToImageFilter(backdrop), promise, total_content_depth);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::restore() {
  GetCanvas().Restore();
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::translate(SkScalar tx, SkScalar ty) {
  GetCanvas().Translate({tx, ty, 0.0});
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::scale(SkScalar sx, SkScalar sy) {
  GetCanvas().Scale({sx, sy, 1.0});
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::rotate(SkScalar degrees) {
  GetCanvas().Rotate(Degrees{degrees});
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::skew(SkScalar sx, SkScalar sy) {
  GetCanvas().Skew(sx, sy);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::transform2DAffine(SkScalar mxx,
                                         SkScalar mxy,
                                         SkScalar mxt,
                                         SkScalar myx,
                                         SkScalar myy,
                                         SkScalar myt) {
  // clang-format off
  transformFullPerspective(
    mxx, mxy,  0, mxt,
    myx, myy,  0, myt,
    0  ,   0,  1,   0,
    0  ,   0,  0,   1
  );
  // clang-format on
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::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) {
  // The order of arguments is row-major but Impeller matrices are
  // column-major.
  // clang-format off
  auto transform = Matrix{
    mxx, myx, mzx, mwx,
    mxy, myy, mzy, mwy,
    mxz, myz, mzz, mwz,
    mxt, myt, mzt, mwt
  };
  // clang-format on
  GetCanvas().Transform(transform);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::transformReset() {
  GetCanvas().ResetTransform();
  GetCanvas().Transform(initial_matrix_);
}

static Entity::ClipOperation ToClipOperation(
    flutter::DlCanvas::ClipOp clip_op) {
  switch (clip_op) {
    case flutter::DlCanvas::ClipOp::kDifference:
      return Entity::ClipOperation::kDifference;
    case flutter::DlCanvas::ClipOp::kIntersect:
      return Entity::ClipOperation::kIntersect;
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::clipRect(const SkRect& rect,
                                ClipOp clip_op,
                                bool is_aa) {
  GetCanvas().ClipRect(skia_conversions::ToRect(rect),
                       ToClipOperation(clip_op));
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::clipRRect(const SkRRect& rrect,
                                 ClipOp sk_op,
                                 bool is_aa) {
  auto clip_op = ToClipOperation(sk_op);
  if (rrect.isRect()) {
    GetCanvas().ClipRect(skia_conversions::ToRect(rrect.rect()), clip_op);
  } else if (rrect.isOval()) {
    GetCanvas().ClipOval(skia_conversions::ToRect(rrect.rect()), clip_op);
  } else if (rrect.isSimple()) {
    GetCanvas().ClipRRect(skia_conversions::ToRect(rrect.rect()),
                          skia_conversions::ToSize(rrect.getSimpleRadii()),
                          clip_op);
  } else {
    GetCanvas().ClipPath(skia_conversions::ToPath(rrect), clip_op);
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::clipPath(const SkPath& path, ClipOp sk_op, bool is_aa) {
  UNIMPLEMENTED;
}

const Path& DlDispatcherBase::GetOrCachePath(const CacheablePath& cache) {
  if (cache.cached_impeller_path.IsEmpty() && !cache.sk_path.isEmpty()) {
    cache.cached_impeller_path = skia_conversions::ToPath(cache.sk_path);
  }
  return cache.cached_impeller_path;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::clipPath(const CacheablePath& cache,
                                ClipOp sk_op,
                                bool is_aa) {
  auto clip_op = ToClipOperation(sk_op);

  SkRect rect;
  if (cache.sk_path.isRect(&rect)) {
    GetCanvas().ClipRect(skia_conversions::ToRect(rect), clip_op);
  } else if (cache.sk_path.isOval(&rect)) {
    GetCanvas().ClipOval(skia_conversions::ToRect(rect), clip_op);
  } else {
    SkRRect rrect;
    if (cache.sk_path.isRRect(&rrect) && rrect.isSimple()) {
      GetCanvas().ClipRRect(skia_conversions::ToRect(rrect.rect()),
                            skia_conversions::ToSize(rrect.getSimpleRadii()),
                            clip_op);
    } else {
      GetCanvas().ClipPath(GetOrCachePath(cache), clip_op);
    }
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawColor(flutter::DlColor color,
                                 flutter::DlBlendMode dl_mode) {
  Paint paint;
  paint.color = skia_conversions::ToColor(color);
  paint.blend_mode = ToBlendMode(dl_mode);
  GetCanvas().DrawPaint(paint);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawPaint() {
  GetCanvas().DrawPaint(paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawLine(const SkPoint& p0, const SkPoint& p1) {
  GetCanvas().DrawLine(skia_conversions::ToPoint(p0),
                       skia_conversions::ToPoint(p1), paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawRect(const SkRect& rect) {
  GetCanvas().DrawRect(skia_conversions::ToRect(rect), paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawOval(const SkRect& bounds) {
  GetCanvas().DrawOval(skia_conversions::ToRect(bounds), paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawCircle(const SkPoint& center, SkScalar radius) {
  GetCanvas().DrawCircle(skia_conversions::ToPoint(center), radius, paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawRRect(const SkRRect& rrect) {
  if (rrect.isSimple()) {
    GetCanvas().DrawRRect(skia_conversions::ToRect(rrect.rect()),
                          skia_conversions::ToSize(rrect.getSimpleRadii()),
                          paint_);
  } else {
    GetCanvas().DrawPath(skia_conversions::ToPath(rrect), paint_);
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawDRRect(const SkRRect& outer, const SkRRect& inner) {
  PathBuilder builder;
  builder.AddPath(skia_conversions::ToPath(outer));
  builder.AddPath(skia_conversions::ToPath(inner));
  GetCanvas().DrawPath(builder.TakePath(FillType::kOdd), paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawPath(const SkPath& path) {
  UNIMPLEMENTED;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawPath(const CacheablePath& cache) {
  SimplifyOrDrawPath(GetCanvas(), cache, paint_);
}

void DlDispatcherBase::SimplifyOrDrawPath(CanvasType& canvas,
                                          const CacheablePath& cache,
                                          const Paint& paint) {
  SkRect rect;

  // We can't "optimize" a path into a rectangle if it's open.
  bool closed;
  if (cache.sk_path.isRect(&rect, &closed) && closed) {
    canvas.DrawRect(skia_conversions::ToRect(rect), paint);
    return;
  }

  SkRRect rrect;
  if (cache.sk_path.isRRect(&rrect) && rrect.isSimple()) {
    canvas.DrawRRect(skia_conversions::ToRect(rrect.rect()),
                     skia_conversions::ToSize(rrect.getSimpleRadii()), paint);
    return;
  }

  SkRect oval;
  if (cache.sk_path.isOval(&oval)) {
    canvas.DrawOval(skia_conversions::ToRect(oval), paint);
    return;
  }

  canvas.DrawPath(GetOrCachePath(cache), paint);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawArc(const SkRect& oval_bounds,
                               SkScalar start_degrees,
                               SkScalar sweep_degrees,
                               bool use_center) {
  PathBuilder builder;
  builder.AddArc(skia_conversions::ToRect(oval_bounds), Degrees(start_degrees),
                 Degrees(sweep_degrees), use_center);
  GetCanvas().DrawPath(builder.TakePath(), paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawPoints(PointMode mode,
                                  uint32_t count,
                                  const SkPoint points[]) {
  Paint paint = paint_;
  paint.style = Paint::Style::kStroke;
  switch (mode) {
    case flutter::DlCanvas::PointMode::kPoints: {
      // Cap::kButt is also treated as a square.
      auto point_style = paint.stroke_cap == Cap::kRound ? PointStyle::kRound
                                                         : PointStyle::kSquare;
      auto radius = paint.stroke_width;
      if (radius > 0) {
        radius /= 2.0;
      }
      GetCanvas().DrawPoints(skia_conversions::ToPoints(points, count), radius,
                             paint, point_style);
    } break;
    case flutter::DlCanvas::PointMode::kLines:
      for (uint32_t i = 1; i < count; i += 2) {
        Point p0 = skia_conversions::ToPoint(points[i - 1]);
        Point p1 = skia_conversions::ToPoint(points[i]);
        GetCanvas().DrawLine(p0, p1, paint);
      }
      break;
    case flutter::DlCanvas::PointMode::kPolygon:
      if (count > 1) {
        Point p0 = skia_conversions::ToPoint(points[0]);
        for (uint32_t i = 1; i < count; i++) {
          Point p1 = skia_conversions::ToPoint(points[i]);
          GetCanvas().DrawLine(p0, p1, paint);
          p0 = p1;
        }
      }
      break;
  }
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawVertices(const flutter::DlVertices* vertices,
                                    flutter::DlBlendMode dl_mode) {
  GetCanvas().DrawVertices(MakeVertices(vertices), ToBlendMode(dl_mode),
                           paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawImage(const sk_sp<flutter::DlImage> image,
                                 const SkPoint point,
                                 flutter::DlImageSampling sampling,
                                 bool render_with_attributes) {
  if (!image) {
    return;
  }

  auto texture = image->impeller_texture();
  if (!texture) {
    return;
  }

  const auto size = texture->GetSize();
  const auto src = SkRect::MakeWH(size.width, size.height);
  const auto dest =
      SkRect::MakeXYWH(point.fX, point.fY, size.width, size.height);

  drawImageRect(image,                      // image
                src,                        // source rect
                dest,                       // destination rect
                sampling,                   // sampling options
                render_with_attributes,     // render with attributes
                SrcRectConstraint::kStrict  // constraint
  );
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawImageRect(
    const sk_sp<flutter::DlImage> image,
    const SkRect& src,
    const SkRect& dst,
    flutter::DlImageSampling sampling,
    bool render_with_attributes,
    SrcRectConstraint constraint = SrcRectConstraint::kFast) {
  GetCanvas().DrawImageRect(
      std::make_shared<Image>(image->impeller_texture()),  // image
      skia_conversions::ToRect(src),                       // source rect
      skia_conversions::ToRect(dst),                       // destination rect
      render_with_attributes ? paint_ : Paint(),           // paint
      ToSamplerDescriptor(sampling)                        // sampling
  );
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawImageNine(const sk_sp<flutter::DlImage> image,
                                     const SkIRect& center,
                                     const SkRect& dst,
                                     flutter::DlFilterMode filter,
                                     bool render_with_attributes) {
  NinePatchConverter converter = {};
  converter.DrawNinePatch(
      std::make_shared<Image>(image->impeller_texture()),
      Rect::MakeLTRB(center.fLeft, center.fTop, center.fRight, center.fBottom),
      skia_conversions::ToRect(dst), ToSamplerDescriptor(filter), &GetCanvas(),
      &paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
                                 const SkRSXform xform[],
                                 const SkRect tex[],
                                 const flutter::DlColor colors[],
                                 int count,
                                 flutter::DlBlendMode mode,
                                 flutter::DlImageSampling sampling,
                                 const SkRect* cull_rect,
                                 bool render_with_attributes) {
  GetCanvas().DrawAtlas(std::make_shared<Image>(atlas->impeller_texture()),
                        skia_conversions::ToRSXForms(xform, count),
                        skia_conversions::ToRects(tex, count),
                        ToColors(colors, count), ToBlendMode(mode),
                        ToSamplerDescriptor(sampling),
                        skia_conversions::ToRect(cull_rect), paint_);
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawDisplayList(
    const sk_sp<flutter::DisplayList> display_list,
    SkScalar opacity) {
  // Save all values that must remain untouched after the operation.
  Paint saved_paint = paint_;
  Matrix saved_initial_matrix = initial_matrix_;

  // Establish a new baseline for interpreting the new DL.
  // Matrix and clip are left untouched, the current
  // transform is saved as the new base matrix, and paint
  // values are reset to defaults.
  initial_matrix_ = GetCanvas().GetCurrentTransform();
  paint_ = Paint();

  // Handle passed opacity in the most brute-force way by using
  // a SaveLayer. If the display_list is able to inherit the
  // opacity, this could also be handled by modulating all of its
  // attribute settings (for example, color), by the indicated
  // opacity.
  int restore_count = GetCanvas().GetSaveCount();
  if (opacity < SK_Scalar1) {
    Paint save_paint;
    save_paint.color = Color(0, 0, 0, opacity);
    GetCanvas().SaveLayer(
        save_paint, skia_conversions::ToRect(display_list->bounds()), nullptr,
        ContentBoundsPromise::kContainsContents, display_list->total_depth());
  } else {
    // The display list may alter the clip, which must be restored to the
    // current clip at the end of playback.
    GetCanvas().Save(display_list->total_depth());
  }

  // TODO(131445): Remove this restriction if we can correctly cull with
  // perspective transforms.
  if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
    // The canvas remembers the screen-space culling bounds clipped by
    // the surface and the history of clip calls. DisplayList can cull
    // the ops based on a rectangle expressed in its "destination bounds"
    // so we need the canvas to transform those into the current local
    // coordinate space into which the DisplayList will be rendered.
    auto cull_bounds = GetCanvas().GetCurrentLocalCullingBounds();
    if (cull_bounds.has_value()) {
      Rect cull_rect = cull_bounds.value();
      display_list->Dispatch(
          *this, SkRect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
                                  cull_rect.GetRight(), cull_rect.GetBottom()));
    } else {
      display_list->Dispatch(*this);
    }
  } else {
    display_list->Dispatch(*this);
  }

  // Restore all saved state back to what it was before we interpreted
  // the display_list
  GetCanvas().RestoreToCount(restore_count);
  initial_matrix_ = saved_initial_matrix;
  paint_ = saved_paint;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawTextBlob(const sk_sp<SkTextBlob> blob,
                                    SkScalar x,
                                    SkScalar y) {
  // When running with Impeller enabled Skia text blobs are converted to
  // Impeller text frames in paragraph_skia.cc
  UNIMPLEMENTED;
}

void DlDispatcherBase::drawTextFrame(
    const std::shared_ptr<TextFrame>& text_frame,
    SkScalar x,
    SkScalar y) {
  GetCanvas().DrawTextFrame(text_frame,             //
                            impeller::Point{x, y},  //
                            paint_                  //
  );
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawShadow(const SkPath& path,
                                  const flutter::DlColor color,
                                  const SkScalar elevation,
                                  bool transparent_occluder,
                                  SkScalar dpr) {
  UNIMPLEMENTED;
}

// |flutter::DlOpReceiver|
void DlDispatcherBase::drawShadow(const CacheablePath& cache,
                                  const flutter::DlColor color,
                                  const SkScalar elevation,
                                  bool transparent_occluder,
                                  SkScalar dpr) {
  Color spot_color = skia_conversions::ToColor(color);
  spot_color.alpha *= 0.25;

  // Compute the spot color -- ported from SkShadowUtils::ComputeTonalColors.
  {
    Scalar max =
        std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
    Scalar min =
        std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
    Scalar luminance = (min + max) * 0.5;

    Scalar alpha_adjust =
        (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
        spot_color.alpha;
    Scalar color_alpha =
        (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
        luminance;
    color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);

    Scalar greyscale_alpha =
        std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);

    Scalar color_scale = color_alpha * (1 - greyscale_alpha);
    Scalar tonal_alpha = color_scale + greyscale_alpha;
    Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
    spot_color = Color(unpremul_scale * spot_color.red,
                       unpremul_scale * spot_color.green,
                       unpremul_scale * spot_color.blue, tonal_alpha);
  }

  Vector3 light_position(0, -1, 1);
  Scalar occluder_z = dpr * elevation;

  constexpr Scalar kLightRadius = 800 / 600;  // Light radius / light height

  Paint paint;
  paint.style = Paint::Style::kFill;
  paint.color = spot_color;
  paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
      .style = FilterContents::BlurStyle::kNormal,
      .sigma = Radius{kLightRadius * occluder_z /
                      GetCanvas().GetCurrentTransform().GetScale().y},
  };

  GetCanvas().Save(1u);
  GetCanvas().PreConcat(
      Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));

  SimplifyOrDrawPath(GetCanvas(), cache, paint);

  GetCanvas().Restore();
}

Picture DlDispatcherBase::EndRecordingAsPicture() {
  TRACE_EVENT0("impeller", "DisplayListDispatcher::EndRecordingAsPicture");
  return GetCanvas().EndRecordingAsPicture();
}

/// Subclasses

DlDispatcher::DlDispatcher() = default;

DlDispatcher::DlDispatcher(IRect cull_rect) : canvas_(cull_rect) {}

DlDispatcher::DlDispatcher(Rect cull_rect) : canvas_(cull_rect) {}

Canvas& DlDispatcher::GetCanvas() {
  return canvas_;
}

ExperimentalDlDispatcher::ExperimentalDlDispatcher(ContentContext& renderer,
                                                   RenderTarget& render_target,
                                                   IRect cull_rect)
    : canvas_(renderer, render_target, cull_rect) {}

Canvas& ExperimentalDlDispatcher::GetCanvas() {
  return canvas_;
}

//// Text Frame Dispatcher

TextFrameDispatcher::TextFrameDispatcher(const ContentContext& renderer,
                                         const Matrix& initial_matrix)
    : renderer_(renderer), matrix_(initial_matrix) {}

void TextFrameDispatcher::save() {
  stack_.emplace_back(matrix_);
}

void TextFrameDispatcher::saveLayer(const SkRect& bounds,
                                    const flutter::SaveLayerOptions options,
                                    const flutter::DlImageFilter* backdrop) {
  save();
}

void TextFrameDispatcher::restore() {
  matrix_ = stack_.back();
  stack_.pop_back();
}

void TextFrameDispatcher::translate(SkScalar tx, SkScalar ty) {
  matrix_ = matrix_.Translate({tx, ty});
}

void TextFrameDispatcher::scale(SkScalar sx, SkScalar sy) {
  matrix_ = matrix_.Scale({sx, sy, 1.0f});
}

void TextFrameDispatcher::rotate(SkScalar degrees) {
  matrix_ = matrix_ * Matrix::MakeRotationZ(Degrees(degrees));
}

void TextFrameDispatcher::skew(SkScalar sx, SkScalar sy) {
  matrix_ = matrix_ * Matrix::MakeSkew(sx, sy);
}

// clang-format off
  // 2x3 2D affine subset of a 4x4 transform in row major order
  void TextFrameDispatcher::transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
                         SkScalar myx, SkScalar myy, SkScalar myt) {
    matrix_ = matrix_ * Matrix::MakeColumn(
        mxx,  myx,  0.0f, 0.0f,
        mxy,  myy,  0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        mxt,  myt,  0.0f, 1.0f
    );
  }

  // full 4x4 transform in row major order
  void TextFrameDispatcher::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) {
    matrix_ = matrix_ * Matrix::MakeColumn(
        mxx, myx, mzx, mwx,
        mxy, myy, mzy, mwy,
        mxz, myz, mzz, mwz,
        mxt, myt, mzt, mwt
    );
  }
// clang-format on

void TextFrameDispatcher::transformReset() {
  matrix_ = Matrix();
}

void TextFrameDispatcher::drawTextFrame(
    const std::shared_ptr<impeller::TextFrame>& text_frame,
    SkScalar x,
    SkScalar y) {
  renderer_.GetLazyGlyphAtlas()->AddTextFrame(*text_frame,
                                              matrix_.GetMaxBasisLengthXY());
}

void TextFrameDispatcher::drawDisplayList(
    const sk_sp<flutter::DisplayList> display_list,
    SkScalar opacity) {
  [[maybe_unused]] size_t stack_depth = stack_.size();
  save();
  display_list->Dispatch(*this);
  restore();
  FML_DCHECK(stack_depth == stack_.size());
}

}  // namespace impeller
