/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrReducedClip_DEFINED
#define GrReducedClip_DEFINED

#include "GrWindowRectangles.h"
#include "SkClipStack.h"
#include "SkTLList.h"

class GrContext;
class GrRenderTargetContext;

/**
 * This class takes a clip stack and produces a reduced set of elements that are equivalent to
 * applying that full stack within a specified query rectangle.
 */
class SK_API GrReducedClip {
public:
    GrReducedClip(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles = 0);

    /**
     * If hasIBounds() is true, this is the bounding box within which the clip elements are valid.
     * The caller must not modify any pixels outside this box. Undefined if hasIBounds() is false.
     */
    const SkIRect& ibounds() const { SkASSERT(fHasIBounds); return fIBounds; }
    int left() const { return this->ibounds().left(); }
    int top() const { return this->ibounds().top(); }
    int width() const { return this->ibounds().width(); }
    int height() const { return this->ibounds().height(); }

    /**
     * Indicates whether ibounds() are defined. They will always be defined if the elements() are
     * nonempty.
     */
    bool hasIBounds() const { return fHasIBounds; }

    /**
     * If nonempty, this is a set of "exclusive" windows within which the clip elements are NOT
     * valid. The caller must not modify any pixels inside these windows.
     */
    const GrWindowRectangles& windowRectangles() const { return fWindowRects; }

    typedef SkTLList<SkClipStack::Element, 16> ElementList;

    /**
     * Populated with a minimal list of elements required to fully implement the clip.
     */
    const ElementList& elements() const { return fElements; }

    /**
     * If elements() are nonempty, uniquely identifies the list of elements within ibounds().
     * Otherwise undefined.
     */
    uint32_t elementsGenID() const { SkASSERT(!fElements.isEmpty()); return fElementsGenID; }

    /**
     * Indicates whether antialiasing is required to process any of the clip elements.
     */
    bool requiresAA() const { return fRequiresAA; }

    enum class InitialState : bool {
        kAllIn,
        kAllOut
    };

    InitialState initialState() const { return fInitialState; }

    bool drawAlphaClipMask(GrRenderTargetContext*) const;
    bool drawStencilClipMask(GrContext*, GrRenderTargetContext*) const;

private:
    void walkStack(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles);
    void addInteriorWindowRectangles(int maxWindowRectangles);
    void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
    bool intersectIBounds(const SkIRect&);

    SkIRect              fIBounds;
    bool                 fHasIBounds;
    GrWindowRectangles   fWindowRects;
    ElementList          fElements;
    uint32_t             fElementsGenID;
    bool                 fRequiresAA;
    InitialState         fInitialState;
};

#endif
