// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h"

#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <vector>

#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/math/rect.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/math/size.h"
#include "cobalt/math/size_conversions.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/render_tree/border.h"
#include "cobalt/render_tree/brush_visitor.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/filter_node.h"
#include "cobalt/render_tree/image_node.h"
#include "cobalt/render_tree/matrix_transform_node.h"
#include "cobalt/render_tree/rect_node.h"
#include "cobalt/render_tree/rect_shadow_node.h"
#include "cobalt/render_tree/rounded_corners.h"
#include "cobalt/render_tree/text_node.h"
#include "cobalt/renderer/rasterizer/common/offscreen_render_coordinate_mapping.h"
#include "cobalt/renderer/rasterizer/common/utils.h"
#include "cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.h"
#include "cobalt/renderer/rasterizer/skia/font.h"
#include "cobalt/renderer/rasterizer/skia/glyph_buffer.h"
#include "cobalt/renderer/rasterizer/skia/image.h"
#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h"
#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h"
#include "cobalt/renderer/rasterizer/skia/software_image.h"
#include "third_party/skia/include/core/SkBlendMode.h"
#include "third_party/skia/include/core/SkClipOp.h"
#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
#include "third_party/skia/include/effects/SkGradientShader.h"

// Setting this define to 1 will enable TRACE_EVENT calls to be made from
// all render node visitations.  It is by default set to 0 because it generates
// enough calls that performance is affected.
#define ENABLE_RENDER_TREE_VISITOR_TRACING 0

// Setting this define to 1 will filter the trace events enabled by
// ENABLE_RENDER_TREE_VISITOR_TRACING so that trace events will only be
// recorded for leaf nodes.
#define FILTER_RENDER_TREE_VISITOR_TRACING 1

// Setting this define to 1 will result in a SkCanvas::flush() call being made
// after each node is visited.  This is useful for debugging Skia code since
// otherwise the actual execution of Skia commands will likely be queued and
// deferred for later execution by skia.
#define ENABLE_FLUSH_AFTER_EVERY_NODE 0

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace skia {

using common::utils::IsOpaque;
using common::utils::IsTransparent;

RenderTreeNodeVisitor::RenderTreeNodeVisitor(
    SkCanvas* render_target,
    const CreateScratchSurfaceFunction* create_scratch_surface_function,
    const base::Closure& reset_skia_context_function,
    const RenderImageFallbackFunction& render_image_fallback_function,
    const RenderImageWithMeshFallbackFunction& render_image_with_mesh_function,
    const ConvertRenderTreeToImageCallback&
        convert_render_tree_to_image_function,
    Type visitor_type)
    : draw_state_(render_target),
      create_scratch_surface_function_(create_scratch_surface_function),
      visitor_type_(visitor_type),
      reset_skia_context_function_(reset_skia_context_function),
      render_image_fallback_function_(render_image_fallback_function),
      render_image_with_mesh_function_(render_image_with_mesh_function),
      convert_render_tree_to_image_function_(
          convert_render_tree_to_image_function) {}

namespace {
// Returns whether the specified node is within the canvas' bounds or not.
bool NodeIsWithinCanvasBounds(const SkMatrix& total_matrix,
                              const SkRect& canvas_bounds,
                              const render_tree::Node& node) {
  SkRect sk_child_bounds(CobaltRectFToSkiaRect(node.GetBounds()));
  SkRect sk_child_bounds_absolute;

  // Use the total matrix to compute the node's bounding rectangle in the
  // canvas' coordinates.
  total_matrix.mapRect(&sk_child_bounds_absolute, sk_child_bounds);

  // Return if the node's bounding rectangle intersects with the canvas'
  // bounding rectangle.
  return sk_child_bounds_absolute.intersect(canvas_bounds);
}

void DrawClearRect(SkCanvas* canvas, const math::RectF& rect,
                   const render_tree::ColorRGBA& color) {
  SkRect sk_rect =
      SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());

  SkPaint paint;
  paint.setBlendMode(SkBlendMode::kSrc);
  paint.setARGB(color.a() * 255, color.r() * 255, color.g() * 255,
                color.b() * 255);

  canvas->drawRect(sk_rect, paint);
}
}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::ClearRectNode* clear_rect_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING && !FILTER_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(ClearRectNode)");
#endif
  DrawClearRect(draw_state_.render_target, clear_rect_node->data().rect,
                clear_rect_node->data().color);
}

void RenderTreeNodeVisitor::Visit(
    render_tree::CompositionNode* composition_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING && !FILTER_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(CompositionNode)");
#endif

  const render_tree::CompositionNode::Children& children =
      composition_node->data().children();

  if (children.empty()) {
    return;
  }

  draw_state_.render_target->translate(composition_node->data().offset().x(),
                                       composition_node->data().offset().y());

  // If we have more than one child (there is little to be gained by performing
  // these calculations otherwise since our bounding rectangle is equal to
  // our child's), retrieve our current total matrix and canvas viewport
  // rectangle so that we can later check if each child is within or outside
  // the viewport.
  base::Optional<SkRect> canvas_bounds;
  base::Optional<SkMatrix> total_matrix;
  if (children.size() > 1) {
    SkIRect canvas_boundsi;
    draw_state_.render_target->getDeviceClipBounds(&canvas_boundsi);
    canvas_bounds = SkRect::Make(canvas_boundsi);
    total_matrix = draw_state_.render_target->getTotalMatrix();
  }

  for (render_tree::CompositionNode::Children::const_iterator iter =
           children.begin();
       iter != children.end(); ++iter) {
    // No need to proceed if the child node is outside our canvas' viewport
    // rectangle.
    if (!canvas_bounds ||
        NodeIsWithinCanvasBounds(*total_matrix, *canvas_bounds, **iter)) {
      (*iter)->Accept(this);
    }
  }

  draw_state_.render_target->translate(-composition_node->data().offset().x(),
                                       -composition_node->data().offset().y());

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

namespace {
SkRRect RoundedRectToSkia(const math::RectF& rect,
                          const render_tree::RoundedCorners& rounded_corners) {
  SkVector radii[4] = {
      {rounded_corners.top_left.horizontal, rounded_corners.top_left.vertical},
      {rounded_corners.top_right.horizontal,
       rounded_corners.top_right.vertical},
      {rounded_corners.bottom_right.horizontal,
       rounded_corners.bottom_right.vertical},
      {rounded_corners.bottom_left.horizontal,
       rounded_corners.bottom_left.vertical},
  };

  SkRRect rrect;
  rrect.setRectRadii(
      SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()), radii);
  return rrect;
}

SkPath RoundedRectToSkiaPath(
    const math::RectF& rect,
    const render_tree::RoundedCorners& rounded_corners) {
  SkPath path;
  path.addRRect(RoundedRectToSkia(rect, rounded_corners),
                SkPath::kCW_Direction);
  return path;
}

void ApplyViewportMask(
    RenderTreeNodeVisitorDrawState* draw_state,
    const base::Optional<render_tree::ViewportFilter>& filter) {
  if (!filter) {
    return;
  }

  if (!filter->has_rounded_corners()) {
    SkRect filter_viewport(CobaltRectFToSkiaRect(filter->viewport()));
    draw_state->render_target->clipRect(filter_viewport);
  } else {
    draw_state->render_target->clipPath(
        RoundedRectToSkiaPath(filter->viewport(), filter->rounded_corners()),
        true /* doAntiAlias */);
    draw_state->clip_is_rect = false;
  }
}

SkColor ToSkColor(const render_tree::ColorRGBA& color) {
  return SkColorSetARGB(color.a() * 255, color.r() * 255, color.g() * 255,
                        color.b() * 255);
}

void ApplyBlurFilterToPaint(
    SkPaint* paint,
    const base::Optional<render_tree::BlurFilter>& blur_filter) {
  if (blur_filter && blur_filter->blur_sigma() > 0.0f) {
    sk_sp<SkImageFilter> skia_blur_filter(SkBlurImageFilter::Make(
        blur_filter->blur_sigma(), blur_filter->blur_sigma(), nullptr));
    paint->setImageFilter(skia_blur_filter);
  }
}

}  // namespace

void RenderTreeNodeVisitor::RenderFilterViaOffscreenSurface(
    const render_tree::FilterNode::Builder& filter_node) {
  const SkMatrix& total_matrix_skia =
      draw_state_.render_target->getTotalMatrix();
  math::Matrix3F total_matrix = SkiaMatrixToCobalt(total_matrix_skia);

  SkIRect canvas_boundsi;
  draw_state_.render_target->getDeviceClipBounds(&canvas_boundsi);

  // Find the global bounds of the filter node's source bounding box, so
  // that we know how large of an offscreen surface to allocate for rendering
  // it within.
  math::RectF global_bounds = IntersectRects(
      total_matrix.MapRect(filter_node.GetBounds()),
      math::Rect(canvas_boundsi.x(), canvas_boundsi.y(), canvas_boundsi.width(),
                 canvas_boundsi.height()));

  math::Rect surface_bounds = math::RoundOut(global_bounds);

  if (surface_bounds.size().IsEmpty()) {
    return;
  }

  // Create a scratch surface upon which we will render the source subtree.
  std::unique_ptr<ScratchSurface> scratch_surface(
      create_scratch_surface_function_->Run(
          math::Size(surface_bounds.width(), surface_bounds.height())));
  if (!scratch_surface) {
    DLOG(ERROR) << "Error creating scratch image surface (width = "
                << surface_bounds.width()
                << ", height = " << surface_bounds.height()
                << "), probably because "
                   "we are low on memory, or the requested dimensions are "
                   "too large or invalid.";
    // In this case, we quit early and not render anything.
    return;
  }

  // Our canvas is guaranteed to already be cleared to ARGB(0, 0, 0, 0).
  SkCanvas* canvas = scratch_surface->GetSurface()->getCanvas();
  DCHECK(canvas);

  // Transform our drawing coordinates so we only render the source tree within
  // the viewport.
  SkMatrix sub_matrix(total_matrix_skia);
  sub_matrix.postTranslate(-surface_bounds.x(), -surface_bounds.y());
  canvas->setMatrix(sub_matrix);

  // Render our source sub-tree into the offscreen surface.
  {
    RenderTreeNodeVisitor sub_visitor(
        canvas, create_scratch_surface_function_, reset_skia_context_function_,
        render_image_fallback_function_, render_image_with_mesh_function_,
        convert_render_tree_to_image_function_, kType_SubVisitor);
    filter_node.source->Accept(&sub_visitor);
  }

  // With the source subtree rendered to our temporary scratch surface, we
  // will now render it to our parent render target with an alpha value set to
  // the opacity value.
  SkPaint paint;
  if (filter_node.opacity_filter) {
    paint.setARGB(filter_node.opacity_filter->opacity() * 255, 255, 255, 255);
  }
  // Use nearest neighbor when filtering texture data, since the source and
  // destination rectangles should be exactly equal.
  paint.setFilterQuality(kNone_SkFilterQuality);

  // We've already used the draw_state_.render_target's scale when rendering to
  // the offscreen surface, so reset the scale for now.
  draw_state_.render_target->save();
  ApplyBlurFilterToPaint(&paint, filter_node.blur_filter);
  ApplyViewportMask(&draw_state_, filter_node.viewport_filter);

  draw_state_.render_target->resetMatrix();

  sk_sp<SkImage> image(scratch_surface->GetSurface()->makeImageSnapshot());
  DCHECK(image);

  SkRect dest_rect =
      SkRect::MakeXYWH(surface_bounds.x(), surface_bounds.y(),
                       surface_bounds.width(), surface_bounds.height());

  SkRect source_rect =
      SkRect::MakeWH(surface_bounds.width(), surface_bounds.height());

  draw_state_.render_target->drawImageRect(image.get(), source_rect, dest_rect,
                                           &paint);

  // Finally restore our parent render target's original transform for the
  // next draw call.
  draw_state_.render_target->restore();
}

namespace {
// Returns true if we permit this source render tree to be rendered under a
// rounded corners filter mask.  In general we avoid doing this becaue it can
// multiply the number of shaders required by the system, however in some cases
// we want to do this still because there is a performance advantage.
bool SourceCanRenderWithRoundedCorners(render_tree::Node* source) {
  // If we are filtering an image, which is a frequent scenario that is worth
  // optimizing for with a custom shader.
  if (source->GetTypeId() == base::GetTypeId<render_tree::ImageNode>()) {
    return true;
  } else if (source->GetTypeId() ==
             base::GetTypeId<render_tree::CompositionNode>()) {
    // If we are a composition of valid sources, then we also allow
    // rendering through a viewport here.
    render_tree::CompositionNode* composition_node =
        base::polymorphic_downcast<render_tree::CompositionNode*>(source);
    typedef render_tree::CompositionNode::Children Children;
    const Children& children = composition_node->data().children();

    for (Children::const_iterator iter = children.begin();
         iter != children.end(); ++iter) {
      if (!SourceCanRenderWithRoundedCorners(iter->get())) {
        return false;
      }
    }
    return true;
  }

  return false;
}

// Tries to render a mapped-to-mesh node, returning false if it fails (which
// would happen if we try to apply a map-to-mesh filter to a render tree node
// that we don't currently support).
bool TryRenderMapToRect(
    render_tree::Node* source, const render_tree::MapToMeshFilter& mesh_filter,
    const RenderTreeNodeVisitor::RenderImageWithMeshFallbackFunction&
        render_onto_mesh,
    RenderTreeNodeVisitorDrawState* draw_state) {
  if (source->GetTypeId() == base::GetTypeId<render_tree::ImageNode>()) {
    render_tree::ImageNode* image_node =
        base::polymorphic_downcast<render_tree::ImageNode*>(source);
    // Since we don't have the tools to render equirectangular meshes directly
    // within Skia, delegate the task to our host rasterizer.
    render_onto_mesh.Run(image_node, mesh_filter, draw_state);
    return true;
  } else if (source->GetTypeId() ==
             base::GetTypeId<render_tree::CompositionNode>()) {
    // If we are a composition of a single node with no translation, and that
    // single node can itself be valid source, then follow through to the
    // single child and try to render it with map-to-mesh.
    render_tree::CompositionNode* composition_node =
        base::polymorphic_downcast<render_tree::CompositionNode*>(source);
    typedef render_tree::CompositionNode::Children Children;
    const Children& children = composition_node->data().children();
    if (children.size() == 1 && composition_node->data().offset().IsZero() &&
        TryRenderMapToRect(children[0].get(), mesh_filter, render_onto_mesh,
                           draw_state)) {
      return true;
    }
  }
  return false;
}

}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
  // If we're dealing with a map-to-mesh filter, handle it all by itself.
  if (filter_node->data().map_to_mesh_filter) {
    render_tree::Node* source = filter_node->data().source.get();
    if (!source) {
      return;
    }

    // WIP TODO: pass in the mesh in the filter here.
    if (TryRenderMapToRect(source, *filter_node->data().map_to_mesh_filter,
                           render_image_with_mesh_function_, &draw_state_)) {
#if ENABLE_FLUSH_AFTER_EVERY_NODE
      draw_state_.render_target->flush();
#endif
    } else {
      DCHECK(false) << "We don't support map-to-mesh on other than ImageNodes.";
    }
    return;
  }

#if ENABLE_RENDER_TREE_VISITOR_TRACING && !FILTER_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(FilterNode)");

  if (filter_node->data().opacity_filter) {
    TRACE_EVENT_INSTANT1("cobalt::renderer", "opacity", "opacity",
                         filter_node->data().opacity_filter->opacity());
  }
  if (filter_node->data().viewport_filter) {
    TRACE_EVENT_INSTANT2(
        "cobalt::renderer", "viewport", "width",
        filter_node->data().viewport_filter->viewport().width(), "height",
        filter_node->data().viewport_filter->viewport().height());
  }
  if (filter_node->data().blur_filter) {
    TRACE_EVENT_INSTANT1("cobalt::renderer", "blur", "blur_sigma",
                         filter_node->data().blur_filter->blur_sigma());
  }
#endif  // ENABLE_RENDER_TREE_VISITOR_TRACING

  if (filter_node->data().opacity_filter &&
      IsTransparent(filter_node->data().opacity_filter->opacity())) {
    // The opacity 0, so we have nothing to render.
    return;
  }

  if ((!filter_node->data().opacity_filter ||
       IsOpaque(filter_node->data().opacity_filter->opacity())) &&
      !filter_node->data().viewport_filter &&
      (!filter_node->data().blur_filter ||
       filter_node->data().blur_filter->blur_sigma() == 0.0f)) {
    // No filter was set, so just rasterize the source render tree as normal.
    filter_node->data().source->Accept(this);
    return;
  }

  const SkMatrix& total_matrix = draw_state_.render_target->getTotalMatrix();

  bool has_rounded_corners =
      filter_node->data().viewport_filter &&
      filter_node->data().viewport_filter->has_rounded_corners();

  // Our general strategy for applying the filter is to render to a texture
  // and then render that texture with a viewport mask applied.  However Skia
  // can optimize for us if we render the subtree source directly with a mask
  // applied.  This has the potential to greatly increase the total number of
  // shaders we need to support, so we only take advantage of this in certain
  // cases.
  bool can_render_with_clip_mask_directly =
      !filter_node->data().blur_filter &&
      // If an opacity filter is being applied, we must render to a separate
      // texture first.
      (!filter_node->data().opacity_filter ||
       common::utils::NodeCanRenderWithOpacity(
           filter_node->data().source.get())) &&
      // If transforms are applied to the viewport, then we will render to
      // a separate texture first.
      total_matrix.rectStaysRect() &&
      // If the viewport mask has rounded corners, in general we will render
      // to a bitmap before applying the mask in order to limit the number of
      // shader permutations (brush types * mask types).  However there are
      // some exceptions, for performance reasons.
      (!has_rounded_corners ||
       SourceCanRenderWithRoundedCorners(filter_node->data().source.get()));

  if (can_render_with_clip_mask_directly) {
    RenderTreeNodeVisitorDrawState original_draw_state(draw_state_);

    draw_state_.render_target->save();
    // Remember the value of |clip_is_rect| because ApplyViewportMask may
    // modify it.
    bool clip_was_rect = draw_state_.clip_is_rect;
    ApplyViewportMask(&draw_state_, filter_node->data().viewport_filter);

    if (filter_node->data().opacity_filter) {
      draw_state_.opacity *= filter_node->data().opacity_filter->opacity();
    }
    filter_node->data().source->Accept(this);

    draw_state_.clip_is_rect = clip_was_rect;
    draw_state_.render_target->restore();
    draw_state_ = original_draw_state;
  } else {
    RenderFilterViaOffscreenSurface(filter_node->data());
  }
#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

namespace {

// Skia expects local texture coordinate transform matrices to map from image
// space coordinates to output rectangle coordinates, i.e. map a texture to
// its output rectangle.  Since render_tree local coordinates assume they are
// operating in a normalized coordinate system, we must perform some
// transformations.
void ConvertLocalTransformMatrixToSkiaShaderFormat(
    const math::Size& input_size,
    const math::RectF& output_rect,
    SkMatrix* local_transform_matrix) {
  // First transform to normalized coordinates, where the input transform
  // specified by local_transform_matrix is expecting to take place.
  local_transform_matrix->preScale(
      1.0f / static_cast<float>(input_size.width()),
      1.0f / static_cast<float>(input_size.height()));

  // After our transformation is applied, we must then transform to the
  // output rectangle space.
  local_transform_matrix->postScale(output_rect.width(), output_rect.height());
  local_transform_matrix->postTranslate(output_rect.x(), output_rect.y());
}

bool IsScaleAndTranslateOnly(const math::Matrix3F& mat) {
  return mat.Get(0, 1) == 0.0f && mat.Get(1, 0) == 0.0f;
}

bool LocalCoordsStaysWithinUnitBox(const math::Matrix3F& mat) {
  return mat.Get(0, 2) <= 0.0f && 1.0f - mat.Get(0, 2) <= mat.Get(0, 0) &&
         mat.Get(1, 2) <= 0.0f && 1.0f - mat.Get(1, 2) <= mat.Get(1, 1);
}

SkPaint CreateSkPaintForImageRendering(
    const RenderTreeNodeVisitorDrawState& draw_state, bool is_opaque) {
  SkPaint paint;
  // |kLow_SkFilterQuality| is used for bilinear interpolation of images.
  paint.setFilterQuality(kLow_SkFilterQuality);

  if (!IsOpaque(draw_state.opacity)) {
    paint.setAlpha(draw_state.opacity * 255);
  } else if (is_opaque && draw_state.clip_is_rect) {
    paint.setBlendMode(SkBlendMode::kSrc);
  }

  return paint;
}

void RenderSinglePlaneImage(SinglePlaneImage* single_plane_image,
                            RenderTreeNodeVisitorDrawState* draw_state,
                            const math::RectF& destination_rect,
                            const math::Matrix3F* local_transform) {
  DCHECK(!single_plane_image->GetContentRegion());
  SkPaint paint = CreateSkPaintForImageRendering(
      *draw_state, single_plane_image->IsOpaque());

  // In the most frequent by far case where the normalized transformed image
  // texture coordinates lie within the unit square, then we must ensure NOT
  // to interpolate texel values with wrapped texels across the image borders.
  // This can result in strips of incorrect colors around the edges of images.
  // Thus, if the normalized texture coordinates lie within the unit box, we
  // will blit the image using drawBitmapRectToRect() which handles the bleeding
  // edge problem for us.

  // Determine the source rectangle, in image texture pixel coordinates.
  const math::Size& img_size = single_plane_image->GetSize();
  sk_sp<SkImage> image = single_plane_image->GetImage();

  if (IsScaleAndTranslateOnly(*local_transform) &&
      LocalCoordsStaysWithinUnitBox(*local_transform)) {
    float width = img_size.width() / local_transform->Get(0, 0);
    float height = img_size.height() / local_transform->Get(1, 1);
    float x = -width * local_transform->Get(0, 2);
    float y = -height * local_transform->Get(1, 2);

    if (image) {
      SkRect src = SkRect::MakeXYWH(x, y, width, height);
      draw_state->render_target->drawImageRect(
          image, src, CobaltRectFToSkiaRect(destination_rect), &paint);
    }
  } else {
    // Use the more general approach which allows arbitrary local texture
    // coordinate matrices.
    SkMatrix skia_local_transform = CobaltMatrixToSkia(*local_transform);

    ConvertLocalTransformMatrixToSkiaShaderFormat(img_size, destination_rect,
                                                  &skia_local_transform);

    if (image) {
      sk_sp<SkShader> image_shader =
          image->makeShader(SkShader::kRepeat_TileMode,
                            SkShader::kRepeat_TileMode, &skia_local_transform);

      paint.setShader(image_shader);

      draw_state->render_target->drawRect(
          CobaltRectFToSkiaRect(destination_rect), paint);
    }
  }
}

void RenderMultiPlaneImage(MultiPlaneImage* multi_plane_image,
                           RenderTreeNodeVisitorDrawState* draw_state,
                           const math::RectF& destination_rect,
                           const math::Matrix3F* local_transform) {
  SB_UNREFERENCED_PARAMETER(multi_plane_image);
  SB_UNREFERENCED_PARAMETER(draw_state);
  SB_UNREFERENCED_PARAMETER(destination_rect);
  SB_UNREFERENCED_PARAMETER(local_transform);

  // Multi-plane images like YUV images are not supported when using the
  // software rasterizers.
  NOTIMPLEMENTED();
  NOTREACHED();
}

}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
  // The image_node may contain nothing. For example, when it represents a video
  // element before any frame is decoded.
  if (!image_node->data().source) {
    return;
  }

#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(ImageNode)");
#endif
  skia::Image* image =
      base::polymorphic_downcast<skia::Image*>(image_node->data().source.get());

  // Creating an image via a resource provider may simply return a frontend
  // image object and enqueue the initialization of a backend image (to be
  // performed on the rasterizer thread).  This function ensures that that
  // initialization is completed.  This would normally not be an issue if
  // an image is submitted as part of a render tree submission, however we
  // may end up with a non-backend-initialized image if a new image is selected
  // during an animation callback (e.g. video playback can do this).
  // This should be a quick operation, and it needs to happen eventually, so
  // if it is not done now, it will be done in the next frame, or the one after
  // that.
  if (image->EnsureInitialized()) {
    // EnsureInitialized() may make a number of GL calls that results in GL
    // state being modified behind Skia's back, therefore we have Skia reset its
    // state in this case.
    if (!reset_skia_context_function_.is_null()) {
      reset_skia_context_function_.Run();
    }
  }

  // We issue different skia rasterization commands to render the image
  // depending on whether it's single or multi planed.
  auto& local_transform = image_node->data().local_transform;

  scoped_refptr<render_tree::Image> fallback_image;
  if (!image->CanRenderInSkia() &&
      !math::IsOnlyScaleAndTranslate(local_transform)) {
    // For anything beyond simply scale and translate.  Convert the image to
    // single plane image and use the skia pipeline.
    fallback_image = convert_render_tree_to_image_function_.Run(
        new render_tree::ImageNode(image));
    image = base::polymorphic_downcast<skia::Image*>(fallback_image.get());
    DCHECK(image->CanRenderInSkia());
  }

  if (image->CanRenderInSkia()) {
    if (image->GetTypeId() == base::GetTypeId<SinglePlaneImage>()) {
      SinglePlaneImage* single_plane_image =
          base::polymorphic_downcast<SinglePlaneImage*>(image);

      RenderSinglePlaneImage(single_plane_image, &draw_state_,
                             image_node->data().destination_rect,
                             &local_transform);
    } else if (image->GetTypeId() == base::GetTypeId<MultiPlaneImage>()) {
      RenderMultiPlaneImage(base::polymorphic_downcast<MultiPlaneImage*>(image),
                            &draw_state_, image_node->data().destination_rect,
                            &local_transform);
    } else {
      NOTREACHED();
    }
  } else {
    render_image_fallback_function_.Run(image_node, &draw_state_);
  }

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

void RenderTreeNodeVisitor::Visit(
    render_tree::MatrixTransform3DNode* matrix_transform_3d_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING && !FILTER_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(MatrixTransform3DNode)");
#endif

  glm::mat4 before = draw_state_.transform_3d;
  draw_state_.transform_3d *= matrix_transform_3d_node->data().transform;

  matrix_transform_3d_node->data().source->Accept(this);

  draw_state_.transform_3d = before;

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

void RenderTreeNodeVisitor::Visit(
    render_tree::MatrixTransformNode* matrix_transform_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING && !FILTER_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(MatrixTransformNode)");
#endif

  // Concatenate the matrix transform to the render target and then continue
  // on with rendering our source.
  draw_state_.render_target->save();

  draw_state_.render_target->concat(
      CobaltMatrixToSkia(matrix_transform_node->data().transform));

  matrix_transform_node->data().source->Accept(this);

  draw_state_.render_target->restore();

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

void RenderTreeNodeVisitor::Visit(
    render_tree::PunchThroughVideoNode* punch_through_video_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(PunchThroughVideoNode)");
#endif

  if (visitor_type_ == kType_SubVisitor) {
    DLOG(ERROR) << "Punch through alpha images cannot be rendered via "
                   "offscreen surfaces (since the offscreen surface will then "
                   "be composed using blending).  Unfortunately, you will have "
                   "to find another way to arrange your render tree if you "
                   "wish to use punch through alpha (e.g. ensure no opacity "
                   "filters exist as an ancestor to this node).";
    // We proceed anyway, just in case things happen to work out.
  }

  const math::RectF& math_rect = punch_through_video_node->data().rect;

  SkRect sk_rect = SkRect::MakeXYWH(math_rect.x(), math_rect.y(),
                                    math_rect.width(), math_rect.height());
  SkMatrix total_matrix = draw_state_.render_target->getTotalMatrix();

  SkRect sk_rect_transformed;
  total_matrix.mapRect(&sk_rect_transformed, sk_rect);

  math::RectF transformed_rectf(
      sk_rect_transformed.x(), sk_rect_transformed.y(),
      sk_rect_transformed.width(), sk_rect_transformed.height());
  math::Rect transformed_rect = math::Rect::RoundFromRectF(transformed_rectf);
  punch_through_video_node->data().set_bounds_cb.Run(transformed_rect);

  DrawClearRect(draw_state_.render_target, math_rect,
                render_tree::ColorRGBA(0, 0, 0, 0));

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

namespace {

class SkiaBrushVisitor : public render_tree::BrushVisitor {
 public:
  SkiaBrushVisitor(SkPaint* paint,
                   const RenderTreeNodeVisitorDrawState& draw_state)
      : paint_(paint), draw_state_(draw_state) {}

  void Visit(
      const cobalt::render_tree::SolidColorBrush* solid_color_brush) override;
  void Visit(const cobalt::render_tree::LinearGradientBrush*
                 linear_gradient_brush) override;
  void Visit(const cobalt::render_tree::RadialGradientBrush*
                 radial_gradient_brush) override;

 private:
  SkPaint* paint_;
  const RenderTreeNodeVisitorDrawState& draw_state_;
};

void SkiaBrushVisitor::Visit(
    const cobalt::render_tree::SolidColorBrush* solid_color_brush) {
  const cobalt::render_tree::ColorRGBA& color = solid_color_brush->color();

  float alpha = color.a() * draw_state_.opacity;
  if (IsOpaque(alpha)) {
    paint_->setBlendMode(SkBlendMode::kSrc);
  } else {
    paint_->setBlendMode(SkBlendMode::kSrcOver);
  }

  paint_->setARGB(alpha * 255, color.r() * 255, color.g() * 255,
                  color.b() * 255);
}

namespace {

// Helper struct to convert render_tree::ColorStopList to a format that Skia
// methods will easily accept.
struct SkiaColorStops {
  explicit SkiaColorStops(const render_tree::ColorStopList& color_stops)
      : colors(color_stops.size()),
        positions(color_stops.size()),
        has_alpha(false) {
    for (size_t i = 0; i < color_stops.size(); ++i) {
      if (color_stops[i].color.HasAlpha()) {
        has_alpha = true;
      }

      colors[i] = ToSkColor(color_stops[i].color);
      positions[i] = color_stops[i].position;
    }
  }

  std::vector<SkColor> colors;
  std::vector<SkScalar> positions;
  bool has_alpha;
};

}  // namespace

void SkiaBrushVisitor::Visit(
    const cobalt::render_tree::LinearGradientBrush* linear_gradient_brush) {
  SkPoint points[2] = {
      {linear_gradient_brush->source().x(),
       linear_gradient_brush->source().y()},
      {linear_gradient_brush->dest().x(), linear_gradient_brush->dest().y()}};

  SkiaColorStops skia_color_stops(linear_gradient_brush->color_stops());

  sk_sp<SkShader> shader(SkGradientShader::MakeLinear(
      points, &skia_color_stops.colors[0], &skia_color_stops.positions[0],
      linear_gradient_brush->color_stops().size(), SkShader::kClamp_TileMode,
      SkGradientShader::kInterpolateColorsInPremul_Flag, NULL));
  paint_->setShader(shader);

  if (!skia_color_stops.has_alpha && IsOpaque(draw_state_.opacity)) {
    paint_->setBlendMode(SkBlendMode::kSrc);
  } else {
    if (!IsOpaque(draw_state_.opacity)) {
      paint_->setAlpha(255 * draw_state_.opacity);
    }
    paint_->setBlendMode(SkBlendMode::kSrcOver);
  }
}

void SkiaBrushVisitor::Visit(
    const cobalt::render_tree::RadialGradientBrush* radial_gradient_brush) {
  SkPoint center = {radial_gradient_brush->center().x(),
                    radial_gradient_brush->center().y()};

  SkiaColorStops skia_color_stops(radial_gradient_brush->color_stops());

  // Skia accepts parameters for a circular gradient only, but it does accept
  // a local matrix that we can use to stretch it into an ellipse, so we set
  // up our circular radius based on our x radius and then stretch the gradient
  // vertically to the y radius.
  SkMatrix local_matrix;
  local_matrix.setIdentity();
  float scale_y =
      radial_gradient_brush->radius_y() / radial_gradient_brush->radius_x();
  // And we'll need to add a translation as well to keep the center at the
  // center despite the scale.
  float translate_y = (1.0f - scale_y) * radial_gradient_brush->center().y();
  local_matrix.setTranslateY(translate_y);
  local_matrix.setScaleY(scale_y);

  sk_sp<SkShader> shader(SkGradientShader::MakeRadial(
      center, radial_gradient_brush->radius_x(), &skia_color_stops.colors[0],
      &skia_color_stops.positions[0],
      radial_gradient_brush->color_stops().size(), SkShader::kClamp_TileMode,
      SkGradientShader::kInterpolateColorsInPremul_Flag, &local_matrix));
  paint_->setShader(shader);

  if (!skia_color_stops.has_alpha && IsOpaque(draw_state_.opacity)) {
    paint_->setBlendMode(SkBlendMode::kSrc);
  } else {
    if (!IsOpaque(draw_state_.opacity)) {
      paint_->setAlpha(255 * draw_state_.opacity);
    }
    paint_->setBlendMode(SkBlendMode::kSrcOver);
  }
}

void DrawRectWithBrush(RenderTreeNodeVisitorDrawState* draw_state,
                       cobalt::render_tree::Brush* brush,
                       const math::RectF& rect) {
  // Setup our paint object according to the brush parameters set on the
  // rectangle.
  SkPaint paint;
  SkiaBrushVisitor brush_visitor(&paint, *draw_state);
  brush->Accept(&brush_visitor);

  if (!draw_state->render_target->getTotalMatrix().preservesAxisAlignment()) {
    // Enable anti-aliasing if we're rendering a rotated or skewed box.
    paint.setAntiAlias(true);
  }

  draw_state->render_target->drawRect(
      SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()), paint);
}

namespace {
class CheckForSolidBrushVisitor : public render_tree::BrushVisitor {
 public:
  CheckForSolidBrushVisitor() : is_solid_brush_(false) {}

  void Visit(
      const cobalt::render_tree::SolidColorBrush* solid_color_brush) override {
    is_solid_brush_ = true;
  }

  void Visit(const cobalt::render_tree::LinearGradientBrush*
                 linear_gradient_brush) override {}
  void Visit(const cobalt::render_tree::RadialGradientBrush*
                 radial_gradient_brush) override {}

  bool is_solid_brush() const { return is_solid_brush_; }

 private:
  bool is_solid_brush_;
};

// DChecks that the brush is a solid brush.
bool CheckForSolidBrush(cobalt::render_tree::Brush* brush) {
  CheckForSolidBrushVisitor visitor;
  brush->Accept(&visitor);
  return visitor.is_solid_brush();
}
}  // namespace

void DrawRoundedRectWithBrush(
    RenderTreeNodeVisitorDrawState* draw_state, render_tree::Brush* brush,
    const math::RectF& rect,
    const render_tree::RoundedCorners& rounded_corners) {
  if (!CheckForSolidBrush(brush)) {
    NOTREACHED() << "Only solid brushes are currently supported for this shape "
                    "in Cobalt.";
    return;
  }

  SkPaint paint;
  SkiaBrushVisitor brush_visitor(&paint, *draw_state);
  brush->Accept(&brush_visitor);

  paint.setAntiAlias(true);
  draw_state->render_target->drawPath(
      RoundedRectToSkiaPath(rect, rounded_corners), paint);
}

void DrawUniformSolidNonRoundRectBorder(
    RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
    float border_width, const render_tree::ColorRGBA& border_color,
    bool anti_alias) {
  SkPaint paint;
  const float alpha = border_color.a() * draw_state->opacity;
  paint.setARGB(alpha * 255, border_color.r() * 255, border_color.g() * 255,
                border_color.b() * 255);
  paint.setAntiAlias(anti_alias);
  if (IsOpaque(alpha)) {
    paint.setBlendMode(SkBlendMode::kSrc);
  } else {
    paint.setBlendMode(SkBlendMode::kSrcOver);
  }
  paint.setStyle(SkPaint::kStroke_Style);
  paint.setStrokeWidth(border_width);
  SkRect skrect;
  const float half_border_width = border_width * 0.5f;
  skrect.set(rect.x() + half_border_width, rect.y() + half_border_width,
             rect.right() - half_border_width,
             rect.bottom() - half_border_width);
  draw_state->render_target->drawRect(skrect, paint);
}

void DrawQuadWithColorIfBorderIsSolid(
    render_tree::BorderStyle border_style,
    RenderTreeNodeVisitorDrawState* draw_state,
    const render_tree::ColorRGBA& color, const SkPoint* points,
    bool anti_alias) {
  if (border_style == render_tree::kBorderStyleSolid) {
    SkPaint paint;
    float alpha = color.a();
    alpha *= draw_state->opacity;
    paint.setARGB(alpha * 255, color.r() * 255, color.g() * 255,
                  color.b() * 255);
    paint.setAntiAlias(anti_alias);
    if (IsOpaque(alpha)) {
      paint.setBlendMode(SkBlendMode::kSrc);
    } else {
      paint.setBlendMode(SkBlendMode::kSrcOver);
    }

    SkPath path;
    path.addPoly(points, 4, true);
    draw_state->render_target->drawPath(path, paint);
  } else {
    DCHECK_EQ(border_style, render_tree::kBorderStyleNone);
  }
}

// Draw 4 trapezoids for 4 directions.
//       A ___________ B
//        |\_________/|
//        ||E       F||
//        ||         ||
//        ||G_______H||
//        |/_________\|
//       C             D
void DrawSolidNonRoundRectBorder(RenderTreeNodeVisitorDrawState* draw_state,
                                 const math::RectF& rect,
                                 const render_tree::Border& border) {
  // Check if the border colors are the same or not to determine whether we
  // should be using antialiasing.  If the border colors are different, then
  // there will be visible diagonal edges in the output and so we would like to
  // render with antialiasing enabled to smooth those diagonal edges.
  bool border_colors_are_same = border.top.color == border.left.color &&
                                border.top.color == border.bottom.color &&
                                border.top.color == border.right.color;

  // If any of the border edges have width less than this threshold, they will
  // use antialiasing as otherwise depending on the border's fractional
  // position, it may have one extra pixel visible, which is a large percentage
  // of its small width.
  const float kAntiAliasWidthThreshold = 3.0f;

  // Use faster draw function if possible.
  if (border_colors_are_same &&
      border.top.style == render_tree::kBorderStyleSolid &&
      border.bottom.style == render_tree::kBorderStyleSolid &&
      border.left.style == render_tree::kBorderStyleSolid &&
      border.right.style == render_tree::kBorderStyleSolid &&
      border.top.width == border.bottom.width &&
      border.top.width == border.left.width &&
      border.top.width == border.right.width) {
    bool anti_alias = border.top.width < kAntiAliasWidthThreshold ||
                      border.bottom.width < kAntiAliasWidthThreshold ||
                      border.left.width < kAntiAliasWidthThreshold ||
                      border.right.width < kAntiAliasWidthThreshold;
    DrawUniformSolidNonRoundRectBorder(draw_state, rect, border.top.width,
                                       border.top.color, anti_alias);
    return;
  }

  // Top
  SkPoint top_points[4] = {
      {rect.x(), rect.y()},                                                 // A
      {rect.x() + border.left.width, rect.y() + border.top.width},          // E
      {rect.right() - border.right.width, rect.y() + border.top.width},     // F
      {rect.right(), rect.y()}};                                            // B
  DrawQuadWithColorIfBorderIsSolid(
      border.top.style, draw_state, border.top.color, top_points,
      border.top.width < kAntiAliasWidthThreshold ? true
                                                  : !border_colors_are_same);

  // Left
  SkPoint left_points[4] = {
      {rect.x(), rect.y()},                                                 // A
      {rect.x(), rect.bottom()},                                            // C
      {rect.x() + border.left.width, rect.bottom() - border.bottom.width},  // G
      {rect.x() + border.left.width, rect.y() + border.top.width}};         // E
  DrawQuadWithColorIfBorderIsSolid(
      border.left.style, draw_state, border.left.color, left_points,
      border.left.width < kAntiAliasWidthThreshold ? true
                                                   : !border_colors_are_same);

  // Bottom
  SkPoint bottom_points[4] = {
      {rect.x() + border.left.width, rect.bottom() - border.bottom.width},  // G
      {rect.x(), rect.bottom()},                                            // C
      {rect.right(), rect.bottom()},                                        // D
      {rect.right() - border.right.width,
       rect.bottom() - border.bottom.width}};                               // H
  DrawQuadWithColorIfBorderIsSolid(
      border.bottom.style, draw_state, border.bottom.color, bottom_points,
      border.bottom.width < kAntiAliasWidthThreshold ? true
                                                     : !border_colors_are_same);

  // Right
  SkPoint right_points[4] = {
      {rect.right() - border.right.width, rect.y() + border.top.width},     // F
      {rect.right() - border.right.width,
       rect.bottom() - border.bottom.width},                                // H
      {rect.right(), rect.bottom()},                                        // D
      {rect.right(), rect.y()}};                                            // B
  DrawQuadWithColorIfBorderIsSolid(
      border.right.style, draw_state, border.right.color, right_points,
      border.right.width < kAntiAliasWidthThreshold ? true
                                                    : !border_colors_are_same);
}

void DrawSolidRoundedRectBorderToRenderTarget(
    RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
    const render_tree::RoundedCorners& rounded_corners,
    const math::RectF& content_rect,
    const render_tree::RoundedCorners& inner_rounded_corners,
    const render_tree::ColorRGBA& color) {
  SkPaint paint;
  paint.setAntiAlias(true);

  float alpha = color.a();
  alpha *= draw_state->opacity;
  paint.setARGB(alpha * 255, color.r() * 255, color.g() * 255, color.b() * 255);
  if (IsOpaque(alpha)) {
    paint.setBlendMode(SkBlendMode::kSrc);
  } else {
    paint.setBlendMode(SkBlendMode::kSrcOver);
  }

  draw_state->render_target->drawDRRect(
      RoundedRectToSkia(rect, rounded_corners),
      RoundedRectToSkia(content_rect, inner_rounded_corners), paint);
}

namespace {
bool IsCircle(const math::SizeF& size,
              const render_tree::RoundedCorners& rounded_corners) {
  if (size.width() != size.height()) {
    return false;
  }

  float radius = size.width() * 0.5f;
  // Corners cannot be "more round" than a circle, so we check using >= rather
  // than == here.
  return rounded_corners.AllCornersGE(
      render_tree::RoundedCorner(radius, radius));
}

bool AllBorderSidesShareSameProperties(const render_tree::Border& border) {
  return (border.top == border.left && border.top == border.right &&
          border.top == border.bottom);
}

base::Optional<SkPoint> CalculateIntersectionPoint(const SkPoint& a,
                                                   const SkPoint& b,
                                                   const SkPoint& c,
                                                   const SkPoint& d) {
  // Given 2 lines, each represented by 2 points (points a and b lie on line 1
  // and points c and d lie on line 2), calculates the intersection point of
  // these 2 lines if they intersect.
  const float ab_width = b.x() - a.x();
  const float ab_height = b.y() - a.y();
  const float cd_width = d.x() - c.x();
  const float cd_height = d.y() - c.y();
  base::Optional<SkPoint> intersection;

  const float determinant = (ab_width * cd_height) - (ab_height * cd_width);
  if (determinant) {
    const float param =
        ((c.x() - a.x()) * cd_height - (c.y() - a.y()) * cd_width) /
        determinant;
    intersection =
        SkPoint({a.x() + param * ab_width, a.y() + param * ab_height});
  }

  return intersection;
}
}  // namespace

void SetUpDrawStateClipPath(RenderTreeNodeVisitorDrawState* draw_state,
                            const SkPoint* points) {
  draw_state->render_target->restore();
  draw_state->render_target->save();

  SkPath path;
  path.addPoly(points, 4, true);

  draw_state->render_target->clipPath(path, SkClipOp::kIntersect, true);
}

void DrawSolidRoundedRectBorderByEdge(
    RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
    const render_tree::RoundedCorners& rounded_corners,
    const math::RectF& content_rect,
    const render_tree::RoundedCorners& inner_rounded_corners,
    const render_tree::Border& border) {
  // Render each border edge separately using SkCanvas::clipPath() to clip out
  // each edge's region from the overall RRect.
  // Divide the area into 4 trapezoids, each represented by 4 points that
  // encompass the clipped out region for a border edge (including the rounded
  // corners). Draw within each clipped out region separately.
  //       A ___________ B
  //        |\_________/|
  //        ||E       F||
  //        ||         ||
  //        ||G_______H||
  //        |/_________\|
  //       C             D
  // NOTE: As described in
  // https://www.w3.org/TR/css3-background/#corner-transitions, the spec does
  // not give an exact function for calculating the center of color/style
  // transitions between adjoining borders, so the following math resembles
  // Chrome: https://cs.chromium.org/BoxBorderPainter::ClipBorderSidePolygon.
  // The center of a transition (represented by points E, F, G and H above) is
  // calculated by finding the intersection point of 2 lines:
  // 1) The line consisting of the outer point (ex: point A, B, C or D) and this
  // outer point adjusted by the corresponding edge's border width (inner
  // point).
  // 2) The line consisting of the inner point adjusted by the corresponding
  // edge's border radius in the x-direction and the inner point adjusted by the
  // corresponding edge's border radius in the y-direction.
  // If no intersection point exists, the transition center is just the inner
  // point.

  base::Optional<SkPoint> intersection;
  // Top Left
  const SkPoint top_left_outer = {rect.x(), rect.y()};
  SkPoint top_left_inner = {rect.x() + border.left.width,
                            rect.y() + border.top.width};

  if (!inner_rounded_corners.top_left.IsSquare()) {
    intersection = CalculateIntersectionPoint(
        top_left_outer, top_left_inner,
        SkPoint({top_left_inner.x() + inner_rounded_corners.top_left.horizontal,
                 top_left_inner.y()}),
        SkPoint(
            {top_left_inner.x(),
             top_left_inner.y() + inner_rounded_corners.top_left.vertical}));
    if (intersection) {
      top_left_inner = SkPoint({intersection->x(), intersection->y()});
    }
  }

  // Top Right
  const SkPoint top_right_outer = {rect.right(), rect.y()};
  SkPoint top_right_inner = {rect.right() - border.right.width,
                             rect.y() + border.top.width};

  if (!inner_rounded_corners.top_right.IsSquare()) {
    intersection = CalculateIntersectionPoint(
        top_right_outer, top_right_inner,
        SkPoint(
            {top_right_inner.x() - inner_rounded_corners.top_right.horizontal,
             top_right_inner.y()}),
        SkPoint(
            {top_right_inner.x(),
             top_right_inner.y() + inner_rounded_corners.top_right.vertical}));
    if (intersection) {
      top_right_inner = SkPoint({intersection->x(), intersection->y()});
    }
  }

  // Bottom Left
  const SkPoint bottom_left_outer = {rect.x(), rect.bottom()};
  SkPoint bottom_left_inner = {rect.x() + border.left.width,
                               rect.bottom() - border.bottom.width};

  if (!inner_rounded_corners.bottom_left.IsSquare()) {
    intersection = CalculateIntersectionPoint(
        bottom_left_outer, bottom_left_inner,
        SkPoint({bottom_left_inner.x() +
                     inner_rounded_corners.bottom_left.horizontal,
                 bottom_left_inner.y()}),
        SkPoint({bottom_left_inner.x(),
                 bottom_left_inner.y() -
                     inner_rounded_corners.bottom_left.vertical}));
    if (intersection) {
      bottom_left_inner = SkPoint({intersection->x(), intersection->y()});
    }
  }

  // Bottom Right
  const SkPoint bottom_right_outer = {rect.right(), rect.bottom()};
  SkPoint bottom_right_inner = {rect.right() - border.right.width,
                                rect.bottom() - border.bottom.width};

  if (!inner_rounded_corners.bottom_right.IsSquare()) {
    intersection = CalculateIntersectionPoint(
        bottom_right_outer, bottom_right_inner,
        SkPoint({bottom_right_inner.x() -
                     inner_rounded_corners.bottom_right.horizontal,
                 bottom_right_inner.y()}),
        SkPoint({bottom_right_inner.x(),
                 bottom_right_inner.y() -
                     inner_rounded_corners.bottom_right.vertical}));
    if (intersection) {
      bottom_right_inner = SkPoint({intersection->x(), intersection->y()});
    }
  }

  // Top
  SkPoint top_points[4] = {top_left_outer, top_left_inner,     // A, E
                           top_right_inner, top_right_outer};  // F, B
  SetUpDrawStateClipPath(draw_state, top_points);
  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
                                           content_rect, inner_rounded_corners,
                                           border.top.color);

  // Left
  SkPoint left_points[4] = {top_left_outer, bottom_left_outer,   // A, C
                            bottom_left_inner, top_left_inner};  // G, E
  SetUpDrawStateClipPath(draw_state, left_points);
  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
                                           content_rect, inner_rounded_corners,
                                           border.left.color);

  // Bottom
  SkPoint bottom_points[4] = {bottom_left_inner, bottom_left_outer,     // G, C
                              bottom_right_outer, bottom_right_inner};  // D, H
  SetUpDrawStateClipPath(draw_state, bottom_points);
  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
                                           content_rect, inner_rounded_corners,
                                           border.bottom.color);

  // Right
  SkPoint right_points[4] = {top_right_inner, bottom_right_inner,   // F, H
                             bottom_right_outer, top_right_outer};  // D, B
  SetUpDrawStateClipPath(draw_state, right_points);
  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
                                           content_rect, inner_rounded_corners,
                                           border.right.color);
}

void DrawSolidRoundedRectBorderSoftware(
    RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
    const render_tree::RoundedCorners& rounded_corners,
    const math::RectF& content_rect,
    const render_tree::RoundedCorners& inner_rounded_corners,
    const render_tree::Border& border) {
  SkImageInfo image_info =
      SkImageInfo::MakeN32(rect.width(), rect.height(), kPremul_SkAlphaType);
  SkBitmap bitmap;

  bool allocation_successful = bitmap.tryAllocPixels(image_info);
  if (!allocation_successful) {
    LOG(WARNING) << "Unable to allocate pixels of size " << rect.width() << "x"
                 << rect.height();
    return;
  }

  SkCanvas canvas(bitmap);
  canvas.clear(SkColorSetARGB(0, 0, 0, 0));

  math::RectF canvas_rect(rect.size());
  math::RectF canvas_content_rect(content_rect);
  canvas_content_rect.Offset(-rect.OffsetFromOrigin());

  RenderTreeNodeVisitorDrawState sub_draw_state(*draw_state);
  sub_draw_state.render_target = &canvas;

  if (AllBorderSidesShareSameProperties(border)) {
    // If all 4 edges share the same border properties, render the whole RRect
    // at once.
    DrawSolidRoundedRectBorderToRenderTarget(
        &sub_draw_state, canvas_rect, rounded_corners, canvas_content_rect,
        inner_rounded_corners, border.top.color);
  } else {
    DrawSolidRoundedRectBorderByEdge(&sub_draw_state, canvas_rect,
                                     rounded_corners, canvas_content_rect,
                                     inner_rounded_corners, border);
  }

  canvas.flush();

  SkPaint render_target_paint;
  render_target_paint.setFilterQuality(kNone_SkFilterQuality);
  draw_state->render_target->drawBitmap(bitmap, rect.x(), rect.y(),
                                        &render_target_paint);
}

void DrawSolidRoundedRectBorder(
    RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
    const render_tree::RoundedCorners& rounded_corners,
    const math::RectF& content_rect,
    const render_tree::RoundedCorners& inner_rounded_corners,
    const render_tree::Border& border) {
  if (IsCircle(rect.size(), rounded_corners) &&
      AllBorderSidesShareSameProperties(border)) {
    // We are able to render circular borders, whose edges have the same
    // properties, using hardware, so introduce a special case for them.
    DrawSolidRoundedRectBorderToRenderTarget(
        draw_state, rect, rounded_corners, content_rect, inner_rounded_corners,
        border.top.color);
  } else {
    // For now we fallback to software for drawing most rounded corner borders,
    // with some situations specified above being special cased. The reason we
    // do this is to limit then number of shaders that need to be implemented.
    NOTIMPLEMENTED_LOG_ONCE()
        << "Warning: Software rasterizing either a solid "
           "rectangle, oval or circle border with different "
           "properties.";
    DrawSolidRoundedRectBorderSoftware(draw_state, rect, rounded_corners,
                                       content_rect, inner_rounded_corners,
                                       border);
  }
}

}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(RectNode)");
#endif
  const math::RectF& rect(rect_node->data().rect);
  math::RectF content_rect(rect);
  if (rect_node->data().border) {
    content_rect.Inset(rect_node->data().border->left.width,
                       rect_node->data().border->top.width,
                       rect_node->data().border->right.width,
                       rect_node->data().border->bottom.width);
  }

  // Apply rounded corners if it exists.
  base::Optional<render_tree::RoundedCorners> inner_rounded_corners;
  if (rect_node->data().rounded_corners) {
    if (rect_node->data().border) {
      inner_rounded_corners = rect_node->data().rounded_corners->Inset(
          rect_node->data().border->left.width,
          rect_node->data().border->top.width,
          rect_node->data().border->right.width,
          rect_node->data().border->bottom.width);
    } else {
      inner_rounded_corners = *rect_node->data().rounded_corners;
    }
  }

  if (rect_node->data().background_brush) {
    if (inner_rounded_corners && !inner_rounded_corners->AreSquares()) {
      DrawRoundedRectWithBrush(&draw_state_,
                               rect_node->data().background_brush.get(),
                               content_rect, *inner_rounded_corners);
    } else {
      DrawRectWithBrush(&draw_state_, rect_node->data().background_brush.get(),
                        content_rect);
    }
  }

  if (rect_node->data().border) {
    if (rect_node->data().rounded_corners) {
      DrawSolidRoundedRectBorder(
          &draw_state_, rect, *rect_node->data().rounded_corners, content_rect,
          *inner_rounded_corners, *rect_node->data().border);
    } else {
      DrawSolidNonRoundRectBorder(&draw_state_, rect,
                                  *rect_node->data().border);
    }
  }

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

namespace {
struct RRect {
  RRect(const math::RectF& rect,
        const base::Optional<render_tree::RoundedCorners>& rounded_corners)
      : rect(rect), rounded_corners(rounded_corners) {}

  void Offset(const math::Vector2dF& offset) { rect.Offset(offset); }

  void Inset(float value) {
    rect.Inset(value, value);
    if (rounded_corners) {
      *rounded_corners = rounded_corners->Inset(value, value, value, value);
    }
  }

  math::RectF rect;
  base::Optional<render_tree::RoundedCorners> rounded_corners;
};

// |shadow_rect| contains the original rect, offset according to the shadow's
// offset, and expanded by the |spread| parameter.  This is the rectangle that
// will actually be passed to the draw command.
RRect GetShadowRect(const render_tree::RectShadowNode& node) {
  RRect shadow_rect(node.data().rect, node.data().rounded_corners);

  shadow_rect.Offset(node.data().shadow.offset);
  float spread = node.data().spread;
  if (node.data().inset) {
    shadow_rect.Inset(spread);
  } else {
    shadow_rect.Inset(-spread);
  }

  return shadow_rect;
}

SkPaint GetPaintForBoxShadow(const render_tree::Shadow& shadow) {
  SkPaint paint;
  paint.setARGB(shadow.color.a() * 255, shadow.color.r() * 255,
                shadow.color.g() * 255, shadow.color.b() * 255);

  sk_sp<SkMaskFilter> mf(
      SkBlurMaskFilter::Make(kNormal_SkBlurStyle, shadow.blur_sigma));
  paint.setMaskFilter(mf);

  return paint;
}

void DrawInsetRectShadowNode(render_tree::RectShadowNode* node,
                             SkCanvas* canvas) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "DrawInsetRectShadowNode()");
#endif
  DCHECK(node->data().inset);

  // We outset the user specified shadow rectangle by the blur extent to know
  // where we should start drawing in order for the blurred result to not appear
  // light at the edges.  There is no point in drawing outside of this rectangle
  // given the fact that all rendering output will be clipped by
  // |node->data().size|.
  const math::RectF& rect = node->data().rect;
  math::RectF shadow_bounds(rect);
  math::Vector2dF blur_extent = node->data().shadow.BlurExtent();
  shadow_bounds.Outset(blur_extent.x(), blur_extent.y());

  // Ensure that |shadow_rect| fits inside of |shadow_bounds| before continuing.
  math::RectF shadow_rect(GetShadowRect(*node).rect);
  shadow_rect.Intersect(shadow_bounds);

  // For inset shadows, we draw 4 rectangles in the shadow's color, all of which
  // wrap around |shadow_rect|, have extents |shadow_bounds|, and are clipped
  // by |rect|.
  SkRect left_shadow_rect =
      SkRect::MakeLTRB(shadow_bounds.x(), shadow_bounds.y(), shadow_rect.x(),
                       shadow_bounds.bottom());
  SkRect top_shadow_rect =
      SkRect::MakeLTRB(shadow_bounds.x(), shadow_bounds.y(),
                       shadow_bounds.right(), shadow_rect.y());
  SkRect right_shadow_rect =
      SkRect::MakeLTRB(shadow_rect.right(), shadow_bounds.y(),
                       shadow_bounds.right(), shadow_bounds.bottom());
  SkRect bottom_shadow_rect =
      SkRect::MakeLTRB(shadow_bounds.x(), shadow_rect.bottom(),
                       shadow_bounds.right(), shadow_bounds.bottom());

  SkRect* draw_rects[] = {
      &left_shadow_rect, &top_shadow_rect, &right_shadow_rect,
      &bottom_shadow_rect,
  };

  SkRect skia_clip_rect = CobaltRectFToSkiaRect(rect);

  SkPaint paint = GetPaintForBoxShadow(node->data().shadow);

  canvas->save();
  canvas->clipRect(skia_clip_rect, SkRegion::kIntersect_Op);
  for (size_t i = 0; i < arraysize(draw_rects); ++i) {
    canvas->drawRect(*draw_rects[i], paint);
  }
  canvas->restore();
}

void DrawOutsetRectShadowNode(render_tree::RectShadowNode* node,
                              SkCanvas* canvas) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "DrawOutsetRectShadowNode()");
#endif
  const math::RectF& rect = node->data().rect;

  SkRect skia_clip_rect = CobaltRectFToSkiaRect(rect);

  const math::RectF shadow_rect(GetShadowRect(*node).rect);
  SkRect skia_draw_rect = CobaltRectFToSkiaRect(shadow_rect);

  SkPaint paint = GetPaintForBoxShadow(node->data().shadow);

  if (node->data().inset) {
    std::swap(skia_clip_rect, skia_draw_rect);
  }

  canvas->save();
  canvas->clipRect(skia_clip_rect, SkClipOp::kDifference, true);
  canvas->drawRect(skia_draw_rect, paint);
  canvas->restore();
}

void DrawRoundedRectShadowNode(render_tree::RectShadowNode* node,
                               SkCanvas* canvas) {
  RRect shadow_rrect = GetShadowRect(*node);

  canvas->save();

  SkRRect skia_clip_rrect =
      RoundedRectToSkia(node->data().rect, *node->data().rounded_corners);
  SkRRect skia_shadow_rrect =
      RoundedRectToSkia(shadow_rrect.rect, *shadow_rrect.rounded_corners);

  if (node->data().inset) {
    // Calculate the outer rect to be large enough such that blurring the outer
    // unseen edge will not affect the visible inner region of the shadow.
    math::RectF outer_rect = shadow_rrect.rect;
    math::Vector2dF common_outer_rect_outset =
        node->data().shadow.BlurExtent() +
        math::Vector2dF(node->data().spread, node->data().spread);
    math::InsetsF outer_rect_outset(
        common_outer_rect_outset.x() + node->data().shadow.offset.x(),
        common_outer_rect_outset.y() + node->data().shadow.offset.y(),
        common_outer_rect_outset.x() - node->data().shadow.offset.x(),
        common_outer_rect_outset.y() - node->data().shadow.offset.y());
    outer_rect_outset.set_left(std::max(0.0f, outer_rect_outset.left()));
    outer_rect_outset.set_top(std::max(0.0f, outer_rect_outset.top()));
    outer_rect_outset.set_right(std::max(0.0f, outer_rect_outset.right()));
    outer_rect_outset.set_bottom(std::max(0.0f, outer_rect_outset.bottom()));
    outer_rect.Outset(outer_rect_outset);

    SkRRect skia_outer_draw_rrect =
        RoundedRectToSkia(outer_rect, *shadow_rrect.rounded_corners);

    canvas->clipRRect(skia_clip_rrect, SkClipOp::kIntersect, true);

    SkPaint paint = GetPaintForBoxShadow(node->data().shadow);
    paint.setAntiAlias(true);

    // Draw a rounded rect "ring".  We draw a ring whose outer rectangle is
    // larger than the clip rectangle so that we can blur it without the outer
    // edge's blur reaching the visible region.
    canvas->drawDRRect(skia_outer_draw_rrect, skia_shadow_rrect, paint);
  } else {
    // Draw a rounded rectangle, possibly blurred, as the shadow rectangle,
    // clipped by node->data().rect.
    canvas->clipRRect(skia_clip_rrect, SkClipOp::kDifference, true);

    SkPaint paint = GetPaintForBoxShadow(node->data().shadow);
    paint.setAntiAlias(true);
    canvas->drawRRect(skia_shadow_rrect, paint);
  }

  canvas->restore();
}

}  // namespace

void RenderTreeNodeVisitor::Visit(
    render_tree::RectShadowNode* rect_shadow_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(RectShadowNode)");
#endif
  DCHECK_EQ(1.0f, draw_state_.opacity);

  if (rect_shadow_node->data().rounded_corners) {
    DrawRoundedRectShadowNode(rect_shadow_node, draw_state_.render_target);
  } else {
    if (rect_shadow_node->data().inset) {
      DrawInsetRectShadowNode(rect_shadow_node, draw_state_.render_target);
    } else {
      DrawOutsetRectShadowNode(rect_shadow_node, draw_state_.render_target);
    }
  }

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

namespace {
void RenderText(SkCanvas* render_target,
                const scoped_refptr<render_tree::GlyphBuffer>& glyph_buffer,
                const render_tree::ColorRGBA& color,
                const math::PointF& position, float blur_sigma) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "RenderText()");
#endif
  if (blur_sigma > 20.0f) {
    // TODO: We could easily switch to using a blur filter at this point.
    //       Ideally we would just use a blur filter to do all blurred text
    //       rendering. Unfortunately, performance is currently terrible when
    //       using blur filters. Since we don't use blur filters (instead the
    //       blur is rasterized into the glyph atlas by software), we choose not
    //       to snap to using them when the blur reaches a certain point to
    //       avoid discontinuity in blur appearance and performance issues.
    NOTIMPLEMENTED() << "Cobalt does not yet support text blurs with Gaussian "
                        "sigmas larger than 20.";
  } else {
    GlyphBuffer* skia_glyph_buffer =
        base::polymorphic_downcast<GlyphBuffer*>(glyph_buffer.get());

    SkPaint paint(Font::GetDefaultSkPaint());
    paint.setARGB(color.a() * 255, color.r() * 255, color.g() * 255,
                  color.b() * 255);

    if (blur_sigma > 0.0f) {
      sk_sp<SkMaskFilter> mf(
          SkBlurMaskFilter::Make(kNormal_SkBlurStyle, blur_sigma,
                                 SkBlurMaskFilter::kHighQuality_BlurFlag));
      paint.setMaskFilter(mf);
    }

    sk_sp<const SkTextBlob> text_blob(skia_glyph_buffer->GetTextBlob());
    render_target->drawTextBlob(text_blob.get(), position.x(), position.y(),
                                paint);
  }
}
}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) {
#if ENABLE_RENDER_TREE_VISITOR_TRACING && !FILTER_RENDER_TREE_VISITOR_TRACING
  TRACE_EVENT0("cobalt::renderer", "Visit(TextNode)");
#endif
  DCHECK_EQ(1.0f, draw_state_.opacity);

  // If blur was used for any of the shadows, apply a little bit of blur
  // to all of them, to ensure that Skia follows the same path for rendering
  // them all (i.e. we don't want the main text to use distance field rendering
  // and the other text use standard bitmap font rendering), which ensures that
  // they will be pixel-aligned with each other.
  float blur_zero_sigma = 0.0f;

  if (text_node->data().shadows) {
    const std::vector<render_tree::Shadow>& shadows =
        *text_node->data().shadows;

    for (size_t i = 0; i < shadows.size(); ++i) {
      if (shadows[i].blur_sigma > 0.0f) {
        // At least one shadow is using a blur, so set a small blur on all
        // text renders.
        blur_zero_sigma = 0.000001f;
        break;
      }
    }

    int num_shadows = static_cast<int>(shadows.size());
    for (int i = num_shadows - 1; i >= 0; --i) {
      // Shadows are rendered in back to front order.
      const render_tree::Shadow& shadow = shadows[i];

      RenderText(
          draw_state_.render_target, text_node->data().glyph_buffer,
          shadow.color, math::PointAtOffsetFromOrigin(text_node->data().offset +
                                                      shadow.offset),
          shadow.blur_sigma == 0.0f ? blur_zero_sigma : shadow.blur_sigma);
    }
  }

  // Finally render the main text.
  RenderText(draw_state_.render_target, text_node->data().glyph_buffer,
             text_node->data().color,
             math::PointAtOffsetFromOrigin(text_node->data().offset),
             blur_zero_sigma);

#if ENABLE_FLUSH_AFTER_EVERY_NODE
  draw_state_.render_target->flush();
#endif
}

}  // namespace skia
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
