/*
 * Copyright (C) 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
 *           (C) 2005 Rob Buis <buis@kde.org>
 *           (C) 2006 Alexander Kellett <lypanov@kde.org>
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.h"

#include "third_party/blink/renderer/core/layout/api/line_layout_svg_inline_text.h"
#include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_shape.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h"
#include "third_party/blink/renderer/core/layout/svg/line/svg_root_inline_box.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
#include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h"
#include "third_party/blink/renderer/core/svg/linear_gradient_attributes.h"
#include "third_party/blink/renderer/core/svg/pattern_attributes.h"
#include "third_party/blink/renderer/core/svg/radial_gradient_attributes.h"
#include "third_party/blink/renderer/core/svg/svg_circle_element.h"
#include "third_party/blink/renderer/core/svg/svg_ellipse_element.h"
#include "third_party/blink/renderer/core/svg/svg_filter_element.h"
#include "third_party/blink/renderer/core/svg/svg_line_element.h"
#include "third_party/blink/renderer/core/svg/svg_linear_gradient_element.h"
#include "third_party/blink/renderer/core/svg/svg_path_element.h"
#include "third_party/blink/renderer/core/svg/svg_path_utilities.h"
#include "third_party/blink/renderer/core/svg/svg_pattern_element.h"
#include "third_party/blink/renderer/core/svg/svg_point_list.h"
#include "third_party/blink/renderer/core/svg/svg_poly_element.h"
#include "third_party/blink/renderer/core/svg/svg_radial_gradient_element.h"
#include "third_party/blink/renderer/core/svg/svg_rect_element.h"
#include "third_party/blink/renderer/platform/graphics/dash_array.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"

#include <math.h>
#include <memory>

namespace blink {

/** class + iomanip to help streaming list separators, i.e. ", " in string "a,
 * b, c, d"
 * Can be used in cases where you don't know which item in the list is the first
 * one to be printed, but still want to avoid strings like ", b, c".
 */
class TextStreamSeparator {
 public:
  TextStreamSeparator(const String& s)
      : separator_(s), need_to_separate_(false) {}

 private:
  friend WTF::TextStream& operator<<(WTF::TextStream&, TextStreamSeparator&);

  String separator_;
  bool need_to_separate_;
};

WTF::TextStream& operator<<(WTF::TextStream& ts, TextStreamSeparator& sep) {
  if (sep.need_to_separate_)
    ts << sep.separator_;
  else
    sep.need_to_separate_ = true;
  return ts;
}

template <typename ValueType>
static void WriteNameValuePair(WTF::TextStream& ts,
                               const char* name,
                               ValueType value) {
  ts << " [" << name << "=" << value << "]";
}

static void WriteSVGResourceIfNotNull(WTF::TextStream& ts,
                                      const char* name,
                                      const StyleSVGResource* value,
                                      TreeScope& tree_scope) {
  if (!value)
    return;
  AtomicString id = SVGURIReference::FragmentIdentifierFromIRIString(
      value->Url(), tree_scope);
  WriteNameValuePair(ts, name, id);
}

template <typename ValueType>
static void WriteNameAndQuotedValue(WTF::TextStream& ts,
                                    const char* name,
                                    ValueType value) {
  ts << " [" << name << "=\"" << value << "\"]";
}

static void WriteQuotedSVGResource(WTF::TextStream& ts,
                                   const char* name,
                                   const StyleSVGResource* value,
                                   TreeScope& tree_scope) {
  DCHECK(value);
  AtomicString id = SVGURIReference::FragmentIdentifierFromIRIString(
      value->Url(), tree_scope);
  WriteNameAndQuotedValue(ts, name, id);
}

template <typename ValueType>
static void WriteIfNotDefault(WTF::TextStream& ts,
                              const char* name,
                              ValueType value,
                              ValueType default_value) {
  if (value != default_value)
    WriteNameValuePair(ts, name, value);
}

WTF::TextStream& operator<<(WTF::TextStream& ts,
                            const AffineTransform& transform) {
  if (transform.IsIdentity()) {
    ts << "identity";
  } else {
    ts << "{m=((" << transform.A() << "," << transform.B() << ")("
       << transform.C() << "," << transform.D() << ")) t=(" << transform.E()
       << "," << transform.F() << ")}";
  }

  return ts;
}

static WTF::TextStream& operator<<(WTF::TextStream& ts, const WindRule rule) {
  switch (rule) {
    case RULE_NONZERO:
      ts << "NON-ZERO";
      break;
    case RULE_EVENODD:
      ts << "EVEN-ODD";
      break;
  }

  return ts;
}

namespace {

template <typename Enum>
String SVGEnumerationToString(Enum value) {
  const SVGEnumerationStringEntries& entries = GetStaticStringEntries<Enum>();

  SVGEnumerationStringEntries::const_iterator it = entries.begin();
  SVGEnumerationStringEntries::const_iterator it_end = entries.end();
  for (; it != it_end; ++it) {
    if (value == it->first)
      return it->second;
  }

  NOTREACHED();
  return String();
}

}  // namespace

static WTF::TextStream& operator<<(WTF::TextStream& ts,
                                   const SVGUnitTypes::SVGUnitType& unit_type) {
  ts << SVGEnumerationToString<SVGUnitTypes::SVGUnitType>(unit_type);
  return ts;
}

static WTF::TextStream& operator<<(WTF::TextStream& ts,
                                   const SVGMarkerUnitsType& marker_unit) {
  ts << SVGEnumerationToString<SVGMarkerUnitsType>(marker_unit);
  return ts;
}

static WTF::TextStream& operator<<(WTF::TextStream& ts,
                                   const SVGMarkerOrientType& orient_type) {
  ts << SVGEnumerationToString<SVGMarkerOrientType>(orient_type);
  return ts;
}

// FIXME: Maybe this should be in GraphicsTypes.cpp
static WTF::TextStream& operator<<(WTF::TextStream& ts, LineCap style) {
  switch (style) {
    case kButtCap:
      ts << "BUTT";
      break;
    case kRoundCap:
      ts << "ROUND";
      break;
    case kSquareCap:
      ts << "SQUARE";
      break;
  }
  return ts;
}

// FIXME: Maybe this should be in GraphicsTypes.cpp
static WTF::TextStream& operator<<(WTF::TextStream& ts, LineJoin style) {
  switch (style) {
    case kMiterJoin:
      ts << "MITER";
      break;
    case kRoundJoin:
      ts << "ROUND";
      break;
    case kBevelJoin:
      ts << "BEVEL";
      break;
  }
  return ts;
}

static WTF::TextStream& operator<<(WTF::TextStream& ts,
                                   const SVGSpreadMethodType& type) {
  ts << SVGEnumerationToString<SVGSpreadMethodType>(type).UpperASCII();
  return ts;
}

static void WriteSVGPaintingResource(
    WTF::TextStream& ts,
    const SVGPaintDescription& paint_description) {
  DCHECK(paint_description.is_valid);
  if (!paint_description.resource) {
    ts << "[type=SOLID] [color=" << paint_description.color << "]";
    return;
  }

  LayoutSVGResourcePaintServer* paint_server_container =
      paint_description.resource;
  SVGElement* element = paint_server_container->GetElement();
  DCHECK(element);

  if (paint_server_container->ResourceType() == kPatternResourceType)
    ts << "[type=PATTERN]";
  else if (paint_server_container->ResourceType() ==
           kLinearGradientResourceType)
    ts << "[type=LINEAR-GRADIENT]";
  else if (paint_server_container->ResourceType() ==
           kRadialGradientResourceType)
    ts << "[type=RADIAL-GRADIENT]";

  ts << " [id=\"" << element->GetIdAttribute() << "\"]";
}

static void WriteStyle(WTF::TextStream& ts, const LayoutObject& object) {
  const ComputedStyle& style = object.StyleRef();
  const SVGComputedStyle& svg_style = style.SvgStyle();

  if (!object.LocalSVGTransform().IsIdentity())
    WriteNameValuePair(ts, "transform", object.LocalSVGTransform());
  WriteIfNotDefault(
      ts, "image rendering", static_cast<int>(style.ImageRendering()),
      static_cast<int>(ComputedStyleInitialValues::InitialImageRendering()));
  WriteIfNotDefault(ts, "opacity", style.Opacity(),
                    ComputedStyleInitialValues::InitialOpacity());
  if (object.IsSVGShape()) {
    const LayoutSVGShape& shape = static_cast<const LayoutSVGShape&>(object);
    DCHECK(shape.GetElement());

    SVGPaintDescription stroke_paint_description =
        LayoutSVGResourcePaintServer::RequestPaintDescription(
            shape, shape.StyleRef(), kApplyToStrokeMode);
    if (stroke_paint_description.is_valid) {
      TextStreamSeparator s(" ");
      ts << " [stroke={" << s;
      WriteSVGPaintingResource(ts, stroke_paint_description);

      SVGLengthContext length_context(shape.GetElement());
      double dash_offset =
          length_context.ValueForLength(svg_style.StrokeDashOffset(), style);
      double stroke_width =
          length_context.ValueForLength(svg_style.StrokeWidth());
      DashArray dash_array = SVGLayoutSupport::ResolveSVGDashArray(
          *svg_style.StrokeDashArray(), style, length_context);

      WriteIfNotDefault(ts, "opacity", svg_style.StrokeOpacity(), 1.0f);
      WriteIfNotDefault(ts, "stroke width", stroke_width, 1.0);
      WriteIfNotDefault(ts, "miter limit", svg_style.StrokeMiterLimit(), 4.0f);
      WriteIfNotDefault(ts, "line cap", svg_style.CapStyle(), kButtCap);
      WriteIfNotDefault(ts, "line join", svg_style.JoinStyle(), kMiterJoin);
      WriteIfNotDefault(ts, "dash offset", dash_offset, 0.0);
      if (!dash_array.IsEmpty())
        WriteNameValuePair(ts, "dash array", dash_array);

      ts << "}]";
    }

    SVGPaintDescription fill_paint_description =
        LayoutSVGResourcePaintServer::RequestPaintDescription(
            shape, shape.StyleRef(), kApplyToFillMode);
    if (fill_paint_description.is_valid) {
      TextStreamSeparator s(" ");
      ts << " [fill={" << s;
      WriteSVGPaintingResource(ts, fill_paint_description);

      WriteIfNotDefault(ts, "opacity", svg_style.FillOpacity(), 1.0f);
      WriteIfNotDefault(ts, "fill rule", svg_style.FillRule(), RULE_NONZERO);
      ts << "}]";
    }
    WriteIfNotDefault(ts, "clip rule", svg_style.ClipRule(), RULE_NONZERO);
  }

  TreeScope& tree_scope = object.GetDocument();
  WriteSVGResourceIfNotNull(ts, "start marker", svg_style.MarkerStartResource(),
                            tree_scope);
  WriteSVGResourceIfNotNull(ts, "middle marker", svg_style.MarkerMidResource(),
                            tree_scope);
  WriteSVGResourceIfNotNull(ts, "end marker", svg_style.MarkerEndResource(),
                            tree_scope);
}

static WTF::TextStream& WritePositionAndStyle(WTF::TextStream& ts,
                                              const LayoutObject& object) {
  ts << " " << object.ObjectBoundingBox();
  WriteStyle(ts, object);
  return ts;
}

static WTF::TextStream& operator<<(WTF::TextStream& ts,
                                   const LayoutSVGShape& shape) {
  WritePositionAndStyle(ts, shape);

  SVGElement* svg_element = shape.GetElement();
  DCHECK(svg_element);
  SVGLengthContext length_context(svg_element);
  const ComputedStyle& style = shape.StyleRef();
  const SVGComputedStyle& svg_style = style.SvgStyle();

  if (IsSVGRectElement(*svg_element)) {
    WriteNameValuePair(ts, "x",
                       length_context.ValueForLength(svg_style.X(), style,
                                                     SVGLengthMode::kWidth));
    WriteNameValuePair(ts, "y",
                       length_context.ValueForLength(svg_style.Y(), style,
                                                     SVGLengthMode::kHeight));
    WriteNameValuePair(ts, "width",
                       length_context.ValueForLength(style.Width(), style,
                                                     SVGLengthMode::kWidth));
    WriteNameValuePair(ts, "height",
                       length_context.ValueForLength(style.Height(), style,
                                                     SVGLengthMode::kHeight));
  } else if (IsSVGLineElement(*svg_element)) {
    SVGLineElement& element = ToSVGLineElement(*svg_element);
    WriteNameValuePair(ts, "x1",
                       element.x1()->CurrentValue()->Value(length_context));
    WriteNameValuePair(ts, "y1",
                       element.y1()->CurrentValue()->Value(length_context));
    WriteNameValuePair(ts, "x2",
                       element.x2()->CurrentValue()->Value(length_context));
    WriteNameValuePair(ts, "y2",
                       element.y2()->CurrentValue()->Value(length_context));
  } else if (IsSVGEllipseElement(*svg_element)) {
    WriteNameValuePair(ts, "cx",
                       length_context.ValueForLength(svg_style.Cx(), style,
                                                     SVGLengthMode::kWidth));
    WriteNameValuePair(ts, "cy",
                       length_context.ValueForLength(svg_style.Cy(), style,
                                                     SVGLengthMode::kHeight));
    WriteNameValuePair(ts, "rx",
                       length_context.ValueForLength(svg_style.Rx(), style,
                                                     SVGLengthMode::kWidth));
    WriteNameValuePair(ts, "ry",
                       length_context.ValueForLength(svg_style.Ry(), style,
                                                     SVGLengthMode::kHeight));
  } else if (IsSVGCircleElement(*svg_element)) {
    WriteNameValuePair(ts, "cx",
                       length_context.ValueForLength(svg_style.Cx(), style,
                                                     SVGLengthMode::kWidth));
    WriteNameValuePair(ts, "cy",
                       length_context.ValueForLength(svg_style.Cy(), style,
                                                     SVGLengthMode::kHeight));
    WriteNameValuePair(ts, "r",
                       length_context.ValueForLength(svg_style.R(), style,
                                                     SVGLengthMode::kOther));
  } else if (IsSVGPolyElement(*svg_element)) {
    WriteNameAndQuotedValue(ts, "points",
                            ToSVGPolyElement(*svg_element)
                                .Points()
                                ->CurrentValue()
                                ->ValueAsString());
  } else if (IsSVGPathElement(*svg_element)) {
    const StylePath& path =
        svg_style.D() ? *svg_style.D() : *StylePath::EmptyPath();
    WriteNameAndQuotedValue(ts, "data",
                            BuildStringFromByteStream(path.ByteStream()));
  } else {
    NOTREACHED();
  }
  return ts;
}

static WTF::TextStream& operator<<(WTF::TextStream& ts,
                                   const LayoutSVGRoot& root) {
  ts << " " << root.FrameRect();
  WriteStyle(ts, root);
  return ts;
}

static void WriteLayoutSVGTextBox(WTF::TextStream& ts,
                                  const LayoutSVGText& text) {
  SVGRootInlineBox* box = ToSVGRootInlineBox(text.FirstRootBox());
  if (!box)
    return;

  // FIXME: Remove this hack, once the new text layout engine is completly
  // landed. We want to preserve the old layout test results for now.
  ts << " contains 1 chunk(s)";

  if (text.Parent() && (text.Parent()->ResolveColor(GetCSSPropertyColor()) !=
                        text.ResolveColor(GetCSSPropertyColor()))) {
    WriteNameValuePair(
        ts, "color",
        text.ResolveColor(GetCSSPropertyColor()).NameForLayoutTreeAsText());
  }
}

static inline void WriteSVGInlineTextBox(WTF::TextStream& ts,
                                         SVGInlineTextBox* text_box,
                                         int indent) {
  Vector<SVGTextFragment>& fragments = text_box->TextFragments();
  if (fragments.IsEmpty())
    return;

  LineLayoutSVGInlineText text_line_layout =
      LineLayoutSVGInlineText(text_box->GetLineLayoutItem());

  const SVGComputedStyle& svg_style = text_line_layout.Style()->SvgStyle();
  String text = text_box->GetLineLayoutItem().GetText();

  unsigned fragments_size = fragments.size();
  for (unsigned i = 0; i < fragments_size; ++i) {
    SVGTextFragment& fragment = fragments.at(i);
    WriteIndent(ts, indent + 1);

    unsigned start_offset = fragment.character_offset;
    unsigned end_offset = fragment.character_offset + fragment.length;

    // FIXME: Remove this hack, once the new text layout engine is completly
    // landed. We want to preserve the old layout test results for now.
    ts << "chunk 1 ";
    ETextAnchor anchor = svg_style.TextAnchor();
    bool is_vertical_text =
        !text_line_layout.Style()->IsHorizontalWritingMode();
    if (anchor == TA_MIDDLE) {
      ts << "(middle anchor";
      if (is_vertical_text)
        ts << ", vertical";
      ts << ") ";
    } else if (anchor == TA_END) {
      ts << "(end anchor";
      if (is_vertical_text)
        ts << ", vertical";
      ts << ") ";
    } else if (is_vertical_text) {
      ts << "(vertical) ";
    }
    start_offset -= text_box->Start();
    end_offset -= text_box->Start();
    // </hack>

    ts << "text run " << i + 1 << " at (" << fragment.x << "," << fragment.y
       << ")";
    ts << " startOffset " << start_offset << " endOffset " << end_offset;
    if (is_vertical_text)
      ts << " height " << fragment.height;
    else
      ts << " width " << fragment.width;

    if (!text_box->IsLeftToRightDirection() || text_box->DirOverride()) {
      ts << (text_box->IsLeftToRightDirection() ? " LTR" : " RTL");
      if (text_box->DirOverride())
        ts << " override";
    }

    ts << ": "
       << QuoteAndEscapeNonPrintables(
              text.Substring(fragment.character_offset, fragment.length))
       << "\n";
  }
}

static inline void WriteSVGInlineTextBoxes(WTF::TextStream& ts,
                                           const LayoutText& text,
                                           int indent) {
  for (InlineTextBox* box : text.TextBoxes()) {
    if (!box->IsSVGInlineTextBox())
      continue;

    WriteSVGInlineTextBox(ts, ToSVGInlineTextBox(box), indent);
  }
}

static void WriteStandardPrefix(WTF::TextStream& ts,
                                const LayoutObject& object,
                                int indent) {
  WriteIndent(ts, indent);
  ts << object.DecoratedName();

  if (object.GetNode())
    ts << " {" << object.GetNode()->nodeName() << "}";
}

static void WriteChildren(WTF::TextStream& ts,
                          const LayoutObject& object,
                          int indent) {
  for (LayoutObject* child = object.SlowFirstChild(); child;
       child = child->NextSibling())
    Write(ts, *child, indent + 1);
}

static inline void WriteCommonGradientProperties(
    WTF::TextStream& ts,
    const GradientAttributes& attrs) {
  WriteNameValuePair(ts, "gradientUnits", attrs.GradientUnits());

  if (attrs.SpreadMethod() != kSVGSpreadMethodPad)
    ts << " [spreadMethod=" << attrs.SpreadMethod() << "]";

  if (!attrs.GradientTransform().IsIdentity())
    ts << " [gradientTransform=" << attrs.GradientTransform() << "]";

  if (attrs.HasStops()) {
    ts << " [stops=( ";
    for (const auto& stop : attrs.Stops())
      ts << stop.color << "@" << stop.stop << " ";
    ts << ")]";
  }
}

void WriteSVGResourceContainer(WTF::TextStream& ts,
                               const LayoutObject& object,
                               int indent) {
  WriteStandardPrefix(ts, object, indent);

  Element* element = ToElement(object.GetNode());
  const AtomicString& id = element->GetIdAttribute();
  WriteNameAndQuotedValue(ts, "id", id);

  LayoutSVGResourceContainer* resource =
      ToLayoutSVGResourceContainer(const_cast<LayoutObject*>(&object));
  DCHECK(resource);

  if (resource->ResourceType() == kMaskerResourceType) {
    LayoutSVGResourceMasker* masker = ToLayoutSVGResourceMasker(resource);
    WriteNameValuePair(ts, "maskUnits", masker->MaskUnits());
    WriteNameValuePair(ts, "maskContentUnits", masker->MaskContentUnits());
    ts << "\n";
  } else if (resource->ResourceType() == kFilterResourceType) {
    LayoutSVGResourceFilter* filter = ToLayoutSVGResourceFilter(resource);
    WriteNameValuePair(ts, "filterUnits", filter->FilterUnits());
    WriteNameValuePair(ts, "primitiveUnits", filter->PrimitiveUnits());
    ts << "\n";
    // Creating a placeholder filter which is passed to the builder.
    FloatRect dummy_rect;
    Filter* dummy_filter =
        Filter::Create(dummy_rect, dummy_rect, 1, Filter::kBoundingBox);
    SVGFilterBuilder builder(dummy_filter->GetSourceGraphic());
    builder.BuildGraph(dummy_filter, ToSVGFilterElement(*filter->GetElement()),
                       dummy_rect);
    if (FilterEffect* last_effect = builder.LastEffect())
      last_effect->ExternalRepresentation(ts, indent + 1);
  } else if (resource->ResourceType() == kClipperResourceType) {
    WriteNameValuePair(ts, "clipPathUnits",
                       ToLayoutSVGResourceClipper(resource)->ClipPathUnits());
    ts << "\n";
  } else if (resource->ResourceType() == kMarkerResourceType) {
    LayoutSVGResourceMarker* marker = ToLayoutSVGResourceMarker(resource);
    WriteNameValuePair(ts, "markerUnits", marker->MarkerUnits());
    ts << " [ref at " << marker->ReferencePoint() << "]";
    ts << " [angle=";
    if (marker->OrientType() != kSVGMarkerOrientAngle)
      ts << marker->OrientType() << "]\n";
    else
      ts << marker->Angle() << "]\n";
  } else if (resource->ResourceType() == kPatternResourceType) {
    LayoutSVGResourcePattern* pattern =
        static_cast<LayoutSVGResourcePattern*>(resource);

    // Dump final results that are used for layout. No use in asking
    // SVGPatternElement for its patternUnits(), as it may link to other
    // patterns using xlink:href, we need to build the full inheritance chain,
    // aka. collectPatternProperties()
    PatternAttributes attributes;
    ToSVGPatternElement(pattern->GetElement())
        ->CollectPatternAttributes(attributes);

    WriteNameValuePair(ts, "patternUnits", attributes.PatternUnits());
    WriteNameValuePair(ts, "patternContentUnits",
                       attributes.PatternContentUnits());

    AffineTransform transform = attributes.PatternTransform();
    if (!transform.IsIdentity())
      ts << " [patternTransform=" << transform << "]";
    ts << "\n";
  } else if (resource->ResourceType() == kLinearGradientResourceType) {
    LayoutSVGResourceLinearGradient* gradient =
        static_cast<LayoutSVGResourceLinearGradient*>(resource);

    // Dump final results that are used for layout. No use in asking
    // SVGGradientElement for its gradientUnits(), as it may link to other
    // gradients using xlink:href, we need to build the full inheritance chain,
    // aka. collectGradientProperties()
    LinearGradientAttributes attributes;
    ToSVGLinearGradientElement(gradient->GetElement())
        ->CollectGradientAttributes(attributes);
    WriteCommonGradientProperties(ts, attributes);

    ts << " [start=" << gradient->StartPoint(attributes)
       << "] [end=" << gradient->EndPoint(attributes) << "]\n";
  } else if (resource->ResourceType() == kRadialGradientResourceType) {
    LayoutSVGResourceRadialGradient* gradient =
        ToLayoutSVGResourceRadialGradient(resource);

    // Dump final results that are used for layout. No use in asking
    // SVGGradientElement for its gradientUnits(), as it may link to other
    // gradients using xlink:href, we need to build the full inheritance chain,
    // aka. collectGradientProperties()
    RadialGradientAttributes attributes;
    ToSVGRadialGradientElement(gradient->GetElement())
        ->CollectGradientAttributes(attributes);
    WriteCommonGradientProperties(ts, attributes);

    FloatPoint focal_point = gradient->FocalPoint(attributes);
    FloatPoint center_point = gradient->CenterPoint(attributes);
    float radius = gradient->Radius(attributes);
    float focal_radius = gradient->FocalRadius(attributes);

    ts << " [center=" << center_point << "] [focal=" << focal_point
       << "] [radius=" << radius << "] [focalRadius=" << focal_radius << "]\n";
  } else {
    ts << "\n";
  }
  WriteChildren(ts, object, indent);
}

void WriteSVGContainer(WTF::TextStream& ts,
                       const LayoutObject& container,
                       int indent) {
  // Currently LayoutSVGResourceFilterPrimitive has no meaningful output.
  if (container.IsSVGResourceFilterPrimitive())
    return;
  WriteStandardPrefix(ts, container, indent);
  WritePositionAndStyle(ts, container);
  ts << "\n";
  WriteResources(ts, container, indent);
  WriteChildren(ts, container, indent);
}

void Write(WTF::TextStream& ts, const LayoutSVGRoot& root, int indent) {
  WriteStandardPrefix(ts, root, indent);
  ts << root << "\n";
  WriteChildren(ts, root, indent);
}

void WriteSVGText(WTF::TextStream& ts, const LayoutSVGText& text, int indent) {
  WriteStandardPrefix(ts, text, indent);
  WritePositionAndStyle(ts, text);
  WriteLayoutSVGTextBox(ts, text);
  ts << "\n";
  WriteResources(ts, text, indent);
  WriteChildren(ts, text, indent);
}

void WriteSVGInline(WTF::TextStream& ts,
                    const LayoutSVGInline& text,
                    int indent) {
  WriteStandardPrefix(ts, text, indent);
  WritePositionAndStyle(ts, text);
  ts << "\n";
  WriteResources(ts, text, indent);
  WriteChildren(ts, text, indent);
}

void WriteSVGInlineText(WTF::TextStream& ts,
                        const LayoutSVGInlineText& text,
                        int indent) {
  WriteStandardPrefix(ts, text, indent);
  WritePositionAndStyle(ts, text);
  ts << "\n";
  WriteResources(ts, text, indent);
  WriteSVGInlineTextBoxes(ts, text, indent);
}

void WriteSVGImage(WTF::TextStream& ts,
                   const LayoutSVGImage& image,
                   int indent) {
  WriteStandardPrefix(ts, image, indent);
  WritePositionAndStyle(ts, image);
  ts << "\n";
  WriteResources(ts, image, indent);
}

void Write(WTF::TextStream& ts, const LayoutSVGShape& shape, int indent) {
  WriteStandardPrefix(ts, shape, indent);
  ts << shape << "\n";
  WriteResources(ts, shape, indent);
}

void WriteResources(WTF::TextStream& ts,
                    const LayoutObject& object,
                    int indent) {
  SVGResources* resources =
      SVGResourcesCache::CachedResourcesForLayoutObject(object);
  if (!resources)
    return;
  const ComputedStyle& style = object.StyleRef();
  TreeScope& tree_scope = object.GetDocument();
  if (LayoutSVGResourceMasker* masker = resources->Masker()) {
    WriteIndent(ts, indent);
    ts << " ";
    WriteQuotedSVGResource(ts, "masker", style.SvgStyle().MaskerResource(),
                           tree_scope);
    ts << " ";
    WriteStandardPrefix(ts, *masker, 0);
    ts << " " << masker->ResourceBoundingBox(&object) << "\n";
  }
  if (LayoutSVGResourceClipper* clipper = resources->Clipper()) {
    DCHECK(style.ClipPath());
    DCHECK_EQ(style.ClipPath()->GetType(), ClipPathOperation::REFERENCE);
    const ReferenceClipPathOperation& clip_path_reference =
        ToReferenceClipPathOperation(*style.ClipPath());
    AtomicString id = SVGURIReference::FragmentIdentifierFromIRIString(
        clip_path_reference.Url(), tree_scope);
    WriteIndent(ts, indent);
    ts << " ";
    WriteNameAndQuotedValue(ts, "clipPath", id);
    ts << " ";
    WriteStandardPrefix(ts, *clipper, 0);
    ts << " " << clipper->ResourceBoundingBox(object.ObjectBoundingBox())
       << "\n";
  }
  if (LayoutSVGResourceFilter* filter = resources->Filter()) {
    DCHECK(style.HasFilter());
    DCHECK_EQ(style.Filter().size(), 1u);
    const FilterOperation& filter_operation = *style.Filter().at(0);
    DCHECK_EQ(filter_operation.GetType(), FilterOperation::REFERENCE);
    const auto& reference_filter_operation =
        ToReferenceFilterOperation(filter_operation);
    AtomicString id = SVGURIReference::FragmentIdentifierFromIRIString(
        reference_filter_operation.Url(), tree_scope);
    WriteIndent(ts, indent);
    ts << " ";
    WriteNameAndQuotedValue(ts, "filter", id);
    ts << " ";
    WriteStandardPrefix(ts, *filter, 0);
    ts << " " << filter->ResourceBoundingBox(&object) << "\n";
  }
}

}  // namespace blink
