/*
 * Copyright (C) 2015 Apple Inc. 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 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 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. 
 */

#pragma once

#include "FloatPoint.h"
#include "FloatRect.h"
#include "FloatRoundedRect.h"
#include "Font.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
#include "Image.h"
#include <wtf/RefCounted.h>
#include <wtf/TypeCasts.h>

#if USE(CG)
#include "GraphicsContextPlatformPrivateCG.h"
#endif

namespace WTF {
class TextStream;
}

namespace WebCore {

struct ImagePaintingOptions;

namespace DisplayList {

enum class ItemType {
    Save,
    Restore,
    Translate,
    Rotate,
    Scale,
    ConcatenateCTM,
    SetState,
    SetLineCap,
    SetLineDash,
    SetLineJoin,
    SetMiterLimit,
    ClearShadow,
    Clip,
    ClipOut,
    ClipOutToPath,
    ClipPath,
    DrawGlyphs,
    DrawImage,
    DrawTiledImage,
    DrawTiledScaledImage,
#if USE(CG) || USE(CAIRO)
    DrawNativeImage,
#endif
    DrawPattern,
    DrawRect,
    DrawLine,
    DrawLinesForText,
    DrawDotsForDocumentMarker,
    DrawEllipse,
    DrawPath,
    DrawFocusRingPath,
    DrawFocusRingRects,
    FillRect,
    FillRectWithColor,
    FillRectWithGradient,
    FillCompositedRect,
    FillRoundedRect,
    FillRectWithRoundedHole,
    FillPath,
    FillEllipse,
    StrokeRect,
    StrokePath,
    StrokeEllipse,
    ClearRect,
    BeginTransparencyLayer,
    EndTransparencyLayer,
#if USE(CG)
    ApplyStrokePattern, // FIXME: should not be a recorded item.
    ApplyFillPattern, // FIXME: should not be a recorded item.
#endif
    ApplyDeviceScaleFactor,
};

class Item : public RefCounted<Item> {
public:
    Item() = delete;

    Item(ItemType type)
        : m_type(type)
    {
    }

    virtual ~Item() = default;

    ItemType type() const
    {
        return m_type;
    }

    virtual void apply(GraphicsContext&) const = 0;

    static constexpr bool isDisplayListItem = true;

    virtual bool isDrawingItem() const { return false; }
    
    // A state item is one preserved by Save/Restore.
    bool isStateItem() const
    {
        return isStateItemType(m_type);
    }

    static bool isStateItemType(ItemType itemType)
    {
        switch (itemType) {
        case ItemType:: Translate:
        case ItemType:: Rotate:
        case ItemType:: Scale:
        case ItemType:: ConcatenateCTM:
        case ItemType:: SetState:
        case ItemType:: SetLineCap:
        case ItemType:: SetLineDash:
        case ItemType:: SetLineJoin:
        case ItemType:: SetMiterLimit:
        case ItemType:: ClearShadow:
            return true;
        default:
            return false;
        }
        return false;
    }

#if !defined(NDEBUG) || !LOG_DISABLED
    WTF::CString description() const;
#endif
    static size_t sizeInBytes(const Item&);

private:
    ItemType m_type;
};

class DrawingItem : public Item {
public:
    DrawingItem(ItemType type)
        : Item(type)
    {
    }

    void setExtent(const FloatRect& r) { m_extent = r; }
    const FloatRect& extent() const { return m_extent.value(); }

    bool extentKnown() const { return static_cast<bool>(m_extent); }

    // Return bounds of this drawing operation in local coordinates.
    // Does not include effets of transform, shadow etc in the state.
    virtual Optional<FloatRect> localBounds(const GraphicsContext&) const { return WTF::nullopt; }

private:
    bool isDrawingItem() const override { return true; }

    Optional<FloatRect> m_extent; // In base coordinates, taking shadows and transforms into account.
};

class Save : public Item {
public:
    static Ref<Save> create()
    {
        return adoptRef(*new Save);
    }

    // Index in the display list of the corresponding Restore item. 0 if unmatched.
    size_t restoreIndex() const { return m_restoreIndex; }
    void setRestoreIndex(size_t index) { m_restoreIndex = index; }

private:
    Save()
        : Item(ItemType::Save)
    {
    }

    void apply(GraphicsContext&) const override;
    
    size_t m_restoreIndex { 0 };
};

class Restore : public Item {
public:
    static Ref<Restore> create()
    {
        return adoptRef(*new Restore);
    }

private:
    Restore()
        : Item(ItemType::Restore)
    {
    }

    void apply(GraphicsContext&) const override;
};

class Translate : public Item {
public:
    static Ref<Translate> create(float x, float y)
    {
        return adoptRef(*new Translate(x, y));
    }

    float x() const { return m_x; }
    float y() const { return m_y; }

private:
    Translate(float x, float y)
        : Item(ItemType::Translate)
        , m_x(x)
        , m_y(y)
    {
    }

    void apply(GraphicsContext&) const override;

    float m_x;
    float m_y;
};

class Rotate : public Item {
public:
    static Ref<Rotate> create(float angleInRadians)
    {
        return adoptRef(*new Rotate(angleInRadians));
    }

    float angle() const { return m_angle; }

private:
    Rotate(float angle)
        : Item(ItemType::Rotate)
        , m_angle(angle)
    {
    }

    void apply(GraphicsContext&) const override;

    float m_angle; // In radians.
};

class Scale : public Item {
public:
    static Ref<Scale> create(const FloatSize& size)
    {
        return adoptRef(*new Scale(size));
    }

    const FloatSize& amount() const { return m_size; }

private:
    Scale(const FloatSize& size)
        : Item(ItemType::Scale)
        , m_size(size)
    {
    }

    void apply(GraphicsContext&) const override;

    FloatSize m_size;
};

class ConcatenateCTM : public Item {
public:
    static Ref<ConcatenateCTM> create(const AffineTransform& matrix)
    {
        return adoptRef(*new ConcatenateCTM(matrix));
    }

    const AffineTransform& transform() const { return m_transform; }

private:
    ConcatenateCTM(const AffineTransform&);

    void apply(GraphicsContext&) const override;

    AffineTransform m_transform;
};

class SetState : public Item {
public:
    static Ref<SetState> create(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags)
    {
        return adoptRef(*new SetState(state, flags));
    }
    
    const GraphicsContextStateChange& state() const { return m_state; }

    void accumulate(const GraphicsContextState&, GraphicsContextState::StateChangeFlags);

    void accumulate(GraphicsContextState&) const;

    static void applyState(GraphicsContext&, const GraphicsContextState&, GraphicsContextState::StateChangeFlags);

    static void dumpStateChanges(WTF::TextStream&, const GraphicsContextState&, GraphicsContextState::StateChangeFlags);
private:
    SetState(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags)
        : Item(ItemType::SetState)
        , m_state(state, flags)
    {
    }

    void apply(GraphicsContext&) const override;

    GraphicsContextStateChange m_state;
};

class SetLineCap : public Item {
public:
    static Ref<SetLineCap> create(LineCap lineCap)
    {
        return adoptRef(*new SetLineCap(lineCap));
    }
    
    LineCap lineCap() const { return m_lineCap; }

private:
    SetLineCap(LineCap lineCap)
        : Item(ItemType::SetLineCap)
        , m_lineCap(lineCap)
    {
    }

    void apply(GraphicsContext&) const override;

    LineCap m_lineCap;
};

class SetLineDash : public Item {
public:
    static Ref<SetLineDash> create(const DashArray& dashArray, float dashOffset)
    {
        return adoptRef(*new SetLineDash(dashArray, dashOffset));
    }

    const DashArray& dashArray() const { return m_dashArray; }
    float dashOffset() const { return m_dashOffset; }

private:
    SetLineDash(const DashArray& dashArray, float dashOffset)
        : Item(ItemType::SetLineDash)
        , m_dashArray(dashArray)
        , m_dashOffset(dashOffset)
    {
    }

    void apply(GraphicsContext&) const override;

    DashArray m_dashArray;
    float m_dashOffset;
};

class SetLineJoin : public Item {
public:
    static Ref<SetLineJoin> create(LineJoin lineJoin)
    {
        return adoptRef(*new SetLineJoin(lineJoin));
    }
    
    LineJoin lineJoin() const { return m_lineJoin; }

private:
    SetLineJoin(LineJoin lineJoin)
        : Item(ItemType::SetLineJoin)
        , m_lineJoin(lineJoin)
    {
    }

    void apply(GraphicsContext&) const override;

    LineJoin m_lineJoin;
};

class SetMiterLimit : public Item {
public:
    static Ref<SetMiterLimit> create(float limit)
    {
        return adoptRef(*new SetMiterLimit(limit));
    }

    float miterLimit() const { return m_miterLimit; }

private:
    SetMiterLimit(float miterLimit)
        : Item(ItemType::SetMiterLimit)
        , m_miterLimit(miterLimit)
    {
    }

    void apply(GraphicsContext&) const override;

    float m_miterLimit;
};

class ClearShadow : public Item {
public:
    static Ref<ClearShadow> create()
    {
        return adoptRef(*new ClearShadow);
    }

private:
    ClearShadow()
        : Item(ItemType::ClearShadow)
    {
    }

    void apply(GraphicsContext&) const override;
};

// FIXME: treat as DrawingItem?
class Clip : public Item {
public:
    static Ref<Clip> create(const FloatRect& rect)
    {
        return adoptRef(*new Clip(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    Clip(const FloatRect& rect)
        : Item(ItemType::Clip)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;

    FloatRect m_rect;
};

class ClipOut : public Item {
public:
    static Ref<ClipOut> create(const FloatRect& rect)
    {
        return adoptRef(*new ClipOut(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    ClipOut(const FloatRect& rect)
        : Item(ItemType::ClipOut)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;

    FloatRect m_rect;
};

class ClipOutToPath : public Item {
public:
    static Ref<ClipOutToPath> create(const Path& path)
    {
        return adoptRef(*new ClipOutToPath(path));
    }

    const Path& path() const { return m_path; }

private:
    ClipOutToPath(const Path& path)
        : Item(ItemType::ClipOutToPath)
        , m_path(path)
    {
    }

    void apply(GraphicsContext&) const override;

    const Path m_path;
};

class ClipPath : public Item {
public:
    static Ref<ClipPath> create(const Path& path, WindRule windRule)
    {
        return adoptRef(*new ClipPath(path, windRule));
    }

    const Path& path() const { return m_path; }
    WindRule windRule() const { return m_windRule; }

private:
    ClipPath(const Path& path, WindRule windRule)
        : Item(ItemType::ClipPath)
        , m_path(path)
        , m_windRule(windRule)
    {
    }

    void apply(GraphicsContext&) const override;

    const Path m_path;
    WindRule m_windRule;
};

class DrawGlyphs : public DrawingItem {
public:
    static Ref<DrawGlyphs> create(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned count, const FloatPoint& blockLocation, const FloatSize& localAnchor, FontSmoothingMode smoothingMode)
    {
        return adoptRef(*new DrawGlyphs(font, glyphs, advances, count, blockLocation, localAnchor, smoothingMode));
    }

    const FloatPoint& blockLocation() const { return m_blockLocation; }
    void setBlockLocation(const FloatPoint& blockLocation) { m_blockLocation = blockLocation; }

    const FloatSize& localAnchor() const { return m_localAnchor; }

    FloatPoint anchorPoint() const { return m_blockLocation + m_localAnchor; }

    const Vector<GlyphBufferGlyph, 128>& glyphs() const { return m_glyphs; }

private:
    DrawGlyphs(const Font&, const GlyphBufferGlyph*, const GlyphBufferAdvance*, unsigned count, const FloatPoint& blockLocation, const FloatSize& localAnchor, FontSmoothingMode);

    void computeBounds();

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    GlyphBuffer generateGlyphBuffer() const;

    Ref<Font> m_font;
    Vector<GlyphBufferGlyph, 128> m_glyphs;
    Vector<GlyphBufferAdvance, 128> m_advances;
    FloatRect m_bounds;
    FloatPoint m_blockLocation;
    FloatSize m_localAnchor;
    FontSmoothingMode m_smoothingMode;
};

class DrawImage : public DrawingItem {
public:
    static Ref<DrawImage> create(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
    {
        return adoptRef(*new DrawImage(image, destination, source, imagePaintingOptions));
    }

    const Image& image() const { return m_image.get(); }
    FloatRect source() const { return m_source; }
    FloatRect destination() const { return m_destination; }

private:
    DrawImage(Image&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions&);

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_destination; }

    mutable Ref<Image> m_image; // FIXME: Drawing images can cause their animations to progress. This shouldn't have to be mutable.
    FloatRect m_destination;
    FloatRect m_source;
    ImagePaintingOptions m_imagePaintingOptions;
};

class DrawTiledImage : public DrawingItem {
public:
    static Ref<DrawTiledImage> create(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
    {
        return adoptRef(*new DrawTiledImage(image, destination, source, tileSize, spacing, imagePaintingOptions));
    }

    const Image& image() const { return m_image.get(); }
    FloatPoint source() const { return m_source; }
    FloatRect destination() const { return m_destination; }

    FloatSize tileSize() const { return m_tileSize; }
    FloatSize spacing() const { return m_spacing; }

private:
    DrawTiledImage(Image&, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions&);

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_destination; }

    mutable Ref<Image> m_image; // FIXME: Drawing images can cause their animations to progress. This shouldn't have to be mutable.
    FloatRect m_destination;
    FloatPoint m_source;
    FloatSize m_tileSize;
    FloatSize m_spacing;
    ImagePaintingOptions m_imagePaintingOptions;
};

class DrawTiledScaledImage : public DrawingItem {
public:
    static Ref<DrawTiledScaledImage> create(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& imagePaintingOptions)
    {
        return adoptRef(*new DrawTiledScaledImage(image, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions));
    }

    const Image& image() const { return m_image.get(); }
    FloatRect source() const { return m_source; }
    FloatRect destination() const { return m_destination; }

private:
    DrawTiledScaledImage(Image&, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions&);

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_destination; }

    mutable Ref<Image> m_image; // FIXME: Drawing images can cause their animations to progress. This shouldn't have to be mutable.
    FloatRect m_destination;
    FloatRect m_source;
    FloatSize m_tileScaleFactor;
    Image::TileRule m_hRule;
    Image::TileRule m_vRule;
    ImagePaintingOptions m_imagePaintingOptions;
};

#if USE(CG) || USE(CAIRO)
class DrawNativeImage : public DrawingItem {
public:
    static Ref<DrawNativeImage> create(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
    {
        return adoptRef(*new DrawNativeImage(image, imageSize, destRect, srcRect, op, blendMode, orientation));
    }

    FloatRect source() const { return m_srcRect; }
    FloatRect destination() const { return m_destination; }

private:
    DrawNativeImage(const NativeImagePtr&, const FloatSize& selfSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator, BlendMode, ImageOrientation);

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_destination; }

#if USE(CG)
    RetainPtr<CGImageRef> m_image;
#endif
    FloatSize m_imageSize;
    FloatRect m_destination;
    FloatRect m_srcRect;
#if USE(CG)
    CompositeOperator m_op;
    BlendMode m_blendMode;
#endif
    ImageOrientation m_orientation;
};
#endif

class DrawPattern : public DrawingItem {
public:
    static Ref<DrawPattern> create(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
    {
        return adoptRef(*new DrawPattern(image, destRect, tileRect, patternTransform, phase, spacing, op, blendMode));
    }

    const Image& image() const { return m_image.get(); }
    const AffineTransform& patternTransform() const { return m_patternTransform; }
    FloatRect tileRect() const { return m_tileRect; }
    FloatRect destRect() const { return m_destination; }
    FloatPoint phase() const { return m_phase; }
    FloatSize spacing() const { return m_spacing; }

private:
    DrawPattern(Image&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform&, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode = BlendMode::Normal);

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_destination; }

    mutable Ref<Image> m_image; // FIXME: Drawing images can cause their animations to progress. This shouldn't have to be mutable.
    AffineTransform m_patternTransform;
    FloatRect m_tileRect;
    FloatRect m_destination;
    FloatPoint m_phase;
    FloatSize m_spacing;
    CompositeOperator m_op;
    BlendMode m_blendMode;
};

// Is DrawingItem because the size of the transparency layer is implicitly the clip bounds.
class BeginTransparencyLayer : public DrawingItem {
public:
    static Ref<BeginTransparencyLayer> create(float opacity)
    {
        return adoptRef(*new BeginTransparencyLayer(opacity));
    }

    float opacity() const { return m_opacity; }

private:
    BeginTransparencyLayer(float opacity)
        : DrawingItem(ItemType::BeginTransparencyLayer)
        , m_opacity(opacity)
    {
    }

    void apply(GraphicsContext&) const override;

    float m_opacity;
};

class EndTransparencyLayer : public DrawingItem {
public:
    static Ref<EndTransparencyLayer> create()
    {
        return adoptRef(*new EndTransparencyLayer);
    }

private:
    EndTransparencyLayer()
        : DrawingItem(ItemType::EndTransparencyLayer)
    {
    }

    void apply(GraphicsContext&) const override;
};

class DrawRect : public DrawingItem {
public:
    static Ref<DrawRect> create(const FloatRect& rect, float borderThickness)
    {
        return adoptRef(*new DrawRect(rect, borderThickness));
    }

    FloatRect rect() const { return m_rect; }
    float borderThickness() const { return m_borderThickness; }

private:
    DrawRect(const FloatRect& rect, float borderThickness)
        : DrawingItem(ItemType::DrawRect)
        , m_rect(rect)
        , m_borderThickness(borderThickness)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
    float m_borderThickness;
};

class DrawLine : public DrawingItem {
public:
    static Ref<DrawLine> create(const FloatPoint& point1, const FloatPoint& point2)
    {
        return adoptRef(*new DrawLine(point1, point2));
    }

    FloatPoint point1() const { return m_point1; }
    FloatPoint point2() const { return m_point2; }

private:
    DrawLine(const FloatPoint& point1, const FloatPoint& point2)
        : DrawingItem(ItemType::DrawLine)
        , m_point1(point1)
        , m_point2(point2)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    FloatPoint m_point1;
    FloatPoint m_point2;
};

class DrawLinesForText : public DrawingItem {
public:
    static Ref<DrawLinesForText> create(const FloatPoint& blockLocation, const FloatSize& localAnchor, float thickness, const DashArray& widths, bool printing, bool doubleLines)
    {
        return adoptRef(*new DrawLinesForText(blockLocation, localAnchor, thickness, widths, printing, doubleLines));
    }

    void setBlockLocation(const FloatPoint& blockLocation) { m_blockLocation = blockLocation; }
    const FloatPoint& blockLocation() const { return m_blockLocation; }
    const FloatSize& localAnchor() const { return m_localAnchor; }
    FloatPoint point() const { return m_blockLocation + m_localAnchor; }
    float thickness() const { return m_thickness; }
    const DashArray& widths() const { return m_widths; }
    bool isPrinting() const { return m_printing; }
    bool doubleLines() const { return m_doubleLines; }

private:
    DrawLinesForText(const FloatPoint& blockLocation, const FloatSize& localAnchor, float thickness, const DashArray& widths, bool printing, bool doubleLines)
        : DrawingItem(ItemType::DrawLinesForText)
        , m_blockLocation(blockLocation)
        , m_localAnchor(localAnchor)
        , m_widths(widths)
        , m_thickness(thickness)
        , m_printing(printing)
        , m_doubleLines(doubleLines)
    {
    }

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    FloatPoint m_blockLocation;
    FloatSize m_localAnchor;
    DashArray m_widths;
    float m_thickness;
    bool m_printing;
    bool m_doubleLines;
};

class DrawDotsForDocumentMarker : public DrawingItem {
public:
    static Ref<DrawDotsForDocumentMarker> create(const FloatRect& rect, DocumentMarkerLineStyle style)
    {
        return adoptRef(*new DrawDotsForDocumentMarker(rect, style));
    }

    FloatRect rect() const { return m_rect; }

private:
    DrawDotsForDocumentMarker(const FloatRect& rect, DocumentMarkerLineStyle style)
        : DrawingItem(ItemType::DrawDotsForDocumentMarker)
        , m_rect(rect)
        , m_style(style)
    {
    }

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    FloatRect m_rect;
    DocumentMarkerLineStyle m_style;
};

class DrawEllipse : public DrawingItem {
public:
    static Ref<DrawEllipse> create(const FloatRect& rect)
    {
        return adoptRef(*new DrawEllipse(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    DrawEllipse(const FloatRect& rect)
        : DrawingItem(ItemType::DrawEllipse)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
};

class DrawPath : public DrawingItem {
public:
    static Ref<DrawPath> create(const Path& path)
    {
        return adoptRef(*new DrawPath(path));
    }

    const Path& path() const { return m_path; }

private:
    DrawPath(const Path& path)
        : DrawingItem(ItemType::DrawPath)
        , m_path(path)
    {
    }

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_path.fastBoundingRect(); }

    const Path m_path;
};

class DrawFocusRingPath : public DrawingItem {
public:
    static Ref<DrawFocusRingPath> create(const Path& path, float width, float offset, const Color& color)
    {
        return adoptRef(*new DrawFocusRingPath(path, width, offset, color));
    }

    const Path& path() const { return m_path; }
    float width() const { return m_width; }
    float offset() const { return m_offset; }
    const Color& color() const { return m_color; }

private:
    DrawFocusRingPath(const Path& path, float width, float offset, const Color& color)
        : DrawingItem(ItemType::DrawFocusRingPath)
        , m_path(path)
        , m_width(width)
        , m_offset(offset)
        , m_color(color)
    {
    }

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    const Path m_path;
    float m_width;
    float m_offset;
    Color m_color;
};

class DrawFocusRingRects : public DrawingItem {
public:
    static Ref<DrawFocusRingRects> create(const Vector<FloatRect>& rects, float width, float offset, const Color& color)
    {
        return adoptRef(*new DrawFocusRingRects(rects, width, offset, color));
    }

    const Vector<FloatRect> rects() const { return m_rects; }
    float width() const { return m_width; }
    float offset() const { return m_offset; }
    const Color& color() const { return m_color; }

private:
    DrawFocusRingRects(const Vector<FloatRect>& rects, float width, float offset, const Color& color)
        : DrawingItem(ItemType::DrawFocusRingRects)
        , m_rects(rects)
        , m_width(width)
        , m_offset(offset)
        , m_color(color)
    {
    }

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    Vector<FloatRect> m_rects;
    float m_width;
    float m_offset;
    Color m_color;
};

class FillRect : public DrawingItem {
public:
    static Ref<FillRect> create(const FloatRect& rect)
    {
        return adoptRef(*new FillRect(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    FillRect(const FloatRect& rect)
        : DrawingItem(ItemType::FillRect)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
};

// FIXME: Make these inherit from FillRect proper.
class FillRectWithColor : public DrawingItem {
public:
    static Ref<FillRectWithColor> create(const FloatRect& rect, const Color& color)
    {
        return adoptRef(*new FillRectWithColor(rect, color));
    }

    FloatRect rect() const { return m_rect; }
    const Color& color() const { return m_color; }

private:
    FillRectWithColor(const FloatRect& rect, const Color& color)
        : DrawingItem(ItemType::FillRectWithColor)
        , m_rect(rect)
        , m_color(color)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
    Color m_color;
};

class FillRectWithGradient : public DrawingItem {
public:
    static Ref<FillRectWithGradient> create(const FloatRect& rect, Gradient& gradient)
    {
        return adoptRef(*new FillRectWithGradient(rect, gradient));
    }

    FloatRect rect() const { return m_rect; }

private:
    FillRectWithGradient(const FloatRect& rect, Gradient& gradient)
        : DrawingItem(ItemType::FillRectWithGradient)
        , m_rect(rect)
        , m_gradient(gradient)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
    mutable Ref<Gradient> m_gradient; // FIXME: Make this not mutable
};

class FillCompositedRect : public DrawingItem {
public:
    static Ref<FillCompositedRect> create(const FloatRect& rect, const Color& color, CompositeOperator op, BlendMode blendMode)
    {
        return adoptRef(*new FillCompositedRect(rect, color, op, blendMode));
    }

    FloatRect rect() const { return m_rect; }
    const Color& color() const { return m_color; }
    CompositeOperator compositeOperator() const { return m_op; }
    BlendMode blendMode() const { return m_blendMode; }

private:
    FillCompositedRect(const FloatRect& rect, const Color& color, CompositeOperator op, BlendMode blendMode)
        : DrawingItem(ItemType::FillCompositedRect)
        , m_rect(rect)
        , m_color(color)
        , m_op(op)
        , m_blendMode(blendMode)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
    Color m_color;
    CompositeOperator m_op;
    BlendMode m_blendMode;
};

class FillRoundedRect : public DrawingItem {
public:
    static Ref<FillRoundedRect> create(const FloatRoundedRect& rect, const Color& color, BlendMode blendMode)
    {
        return adoptRef(*new FillRoundedRect(rect, color, blendMode));
    }

    const FloatRoundedRect& roundedRect() const { return m_rect; }
    const Color& color() const { return m_color; }
    BlendMode blendMode() const { return m_blendMode; }

private:
    FillRoundedRect(const FloatRoundedRect& rect, const Color& color, BlendMode blendMode)
        : DrawingItem(ItemType::FillRoundedRect)
        , m_rect(rect)
        , m_color(color)
        , m_blendMode(blendMode)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect.rect(); }

    FloatRoundedRect m_rect;
    Color m_color;
    BlendMode m_blendMode;
};

class FillRectWithRoundedHole : public DrawingItem {
public:
    static Ref<FillRectWithRoundedHole> create(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
    {
        return adoptRef(*new FillRectWithRoundedHole(rect, roundedHoleRect, color));
    }

    const FloatRect& rect() const { return m_rect; }
    const FloatRoundedRect& roundedHoleRect() const { return m_roundedHoleRect; }
    const Color& color() const { return m_color; }

private:
    FillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
        : DrawingItem(ItemType::FillRectWithRoundedHole)
        , m_rect(rect)
        , m_roundedHoleRect(roundedHoleRect)
        , m_color(color)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
    FloatRoundedRect m_roundedHoleRect;
    Color m_color;
};

class FillPath : public DrawingItem {
public:
    static Ref<FillPath> create(const Path& path)
    {
        return adoptRef(*new FillPath(path));
    }

    const Path& path() const { return m_path; }

private:
    FillPath(const Path& path)
        : DrawingItem(ItemType::FillPath)
        , m_path(path)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_path.fastBoundingRect(); }

    const Path m_path;
};

class FillEllipse : public DrawingItem {
public:
    static Ref<FillEllipse> create(const FloatRect& rect)
    {
        return adoptRef(*new FillEllipse(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    FillEllipse(const FloatRect& rect)
        : DrawingItem(ItemType::FillEllipse)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;

    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
};

class StrokeRect : public DrawingItem {
public:
    static Ref<StrokeRect> create(const FloatRect& rect, float lineWidth)
    {
        return adoptRef(*new StrokeRect(rect, lineWidth));
    }

    FloatRect rect() const { return m_rect; }
    float lineWidth() const { return m_lineWidth; }

private:
    StrokeRect(const FloatRect& rect, float lineWidth)
        : DrawingItem(ItemType::StrokeRect)
        , m_rect(rect)
        , m_lineWidth(lineWidth)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    FloatRect m_rect;
    float m_lineWidth;
};

class StrokePath : public DrawingItem {
public:
    static Ref<StrokePath> create(const Path& path)
    {
        return adoptRef(*new StrokePath(path));
    }

    const Path& path() const { return m_path; }

private:
    StrokePath(const Path& path)
        : DrawingItem(ItemType::StrokePath)
        , m_path(path)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    const Path m_path;
    FloatPoint m_blockLocation;
};

class StrokeEllipse : public DrawingItem {
public:
    static Ref<StrokeEllipse> create(const FloatRect& rect)
    {
        return adoptRef(*new StrokeEllipse(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    StrokeEllipse(const FloatRect& rect)
        : DrawingItem(ItemType::StrokeEllipse)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override;

    FloatRect m_rect;
};

class ClearRect : public DrawingItem {
public:
    static Ref<ClearRect> create(const FloatRect& rect)
    {
        return adoptRef(*new ClearRect(rect));
    }

    FloatRect rect() const { return m_rect; }

private:
    ClearRect(const FloatRect& rect)
        : DrawingItem(ItemType::ClearRect)
        , m_rect(rect)
    {
    }

    void apply(GraphicsContext&) const override;
    Optional<FloatRect> localBounds(const GraphicsContext&) const override { return m_rect; }

    FloatRect m_rect;
};

#if USE(CG)
class ApplyStrokePattern : public Item {
public:
    static Ref<ApplyStrokePattern> create()
    {
        return adoptRef(*new ApplyStrokePattern);
    }

private:
    ApplyStrokePattern()
        : Item(ItemType::ApplyStrokePattern)
    {
    }

    void apply(GraphicsContext&) const override;
};

class ApplyFillPattern : public Item {
public:
    static Ref<ApplyFillPattern> create()
    {
        return adoptRef(*new ApplyFillPattern);
    }

private:
    ApplyFillPattern()
        : Item(ItemType::ApplyFillPattern)
    {
    }

    void apply(GraphicsContext&) const override;
};
#endif

class ApplyDeviceScaleFactor : public Item {
public:
    static Ref<ApplyDeviceScaleFactor> create(float scaleFactor)
    {
        return adoptRef(*new ApplyDeviceScaleFactor(scaleFactor));
    }

    float scaleFactor() const { return m_scaleFactor; }

private:
    ApplyDeviceScaleFactor(float scaleFactor)
        : Item(ItemType::ApplyDeviceScaleFactor)
        , m_scaleFactor(scaleFactor)
    {
    }

    void apply(GraphicsContext&) const override;

    float m_scaleFactor;
};

WTF::TextStream& operator<<(WTF::TextStream&, const Item&);

} // namespace DisplayList
} // namespace WebCore


#define SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_DRAWINGITEM(ToValueTypeName, predicate) \
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::DisplayList::ToValueTypeName) \
    static bool isType(const WebCore::DisplayList::Item& object) { return object.predicate; } \
SPECIALIZE_TYPE_TRAITS_END()

SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_DRAWINGITEM(DrawingItem, isDrawingItem())

#define SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ToValueTypeName) \
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::DisplayList::ToValueTypeName) \
    static bool isType(const WebCore::DisplayList::Item& item) { return item.type() == WebCore::DisplayList::ItemType::ToValueTypeName; } \
SPECIALIZE_TYPE_TRAITS_END()

SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Save)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Restore)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Translate)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Rotate)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Scale)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ConcatenateCTM)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetState)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetLineCap)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetLineDash)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetLineJoin)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetMiterLimit)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Clip)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ClipOut)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ClipOutToPath)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ClipPath)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawGlyphs)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawImage)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawTiledImage)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawTiledScaledImage)
#if USE(CG) || USE(CAIRO)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawNativeImage)
#endif
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawPattern)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawRect)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawLine)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawLinesForText)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawDotsForDocumentMarker)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawEllipse)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawPath)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawFocusRingPath)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(DrawFocusRingRects)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillRect)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillRectWithColor)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillRectWithGradient)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillCompositedRect)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillRoundedRect)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillRectWithRoundedHole)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillPath)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillEllipse)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokeRect)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokePath)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokeEllipse)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ClearRect)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(BeginTransparencyLayer)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(EndTransparencyLayer)
#if USE(CG)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ApplyStrokePattern)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ApplyFillPattern)
#endif
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ApplyDeviceScaleFactor)
SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ClearShadow)

