/*
 * 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 SkPipeCanvas_DEFINED
#define SkPipeCanvas_DEFINED

#include "SkCanvasVirtualEnforcer.h"
#include "SkDeduper.h"
#include "SkImage.h"
#include "SkNoDrawCanvas.h"
#include "SkPipe.h"
#include "SkTypeface.h"
#include "SkWriteBuffer.h"

class SkPipeCanvas;
class SkPipeWriter;

template <typename T> class SkTIndexSet {
public:
    void reset() { fArray.reset(); }

    // returns the found index or 0
    int find(const T& key) const {
        const Rec* stop = fArray.end();
        for (const Rec* curr = fArray.begin(); curr < stop; ++curr) {
            if (key == curr->fKey) {
                return curr->fIndex;
            }
        }
        return 0;
    }

    // returns the new index
    int add(const T& key) {
        Rec* rec = fArray.append();
        rec->fKey = key;
        rec->fIndex = fNextIndex++;
        return rec->fIndex;
    }

private:
    struct Rec {
        T   fKey;
        int fIndex;
    };

    SkTDArray<Rec>  fArray;
    int fNextIndex = 1;
};

class SkPipeDeduper : public SkDeduper {
public:
    void resetCaches() {
        fImages.reset();
        fPictures.reset();
        fTypefaces.reset();
        fFactories.reset();
    }

    void setCanvas(SkPipeCanvas* canvas) { fPipeCanvas = canvas; }
    void setStream(SkWStream* stream) { fStream = stream; }
    void setSerialProcs(const SkSerialProcs& procs) { fProcs = procs; }

    // returns 0 if not found
    int findImage(SkImage* image) const { return fImages.find(image->uniqueID()); }
    int findPicture(SkPicture* picture) const { return fPictures.find(picture->uniqueID()); }

    int findOrDefineImage(SkImage*) override;
    int findOrDefinePicture(SkPicture*) override;
    int findOrDefineTypeface(SkTypeface*) override;
    int findOrDefineFactory(SkFlattenable*) override;

private:
    SkPipeCanvas*           fPipeCanvas = nullptr;
    SkWStream*              fStream = nullptr;
    SkSerialProcs           fProcs;

    // All our keys (at the moment) are 32bit uniqueIDs
    SkTIndexSet<uint32_t>   fImages;
    SkTIndexSet<uint32_t>   fPictures;
    SkTIndexSet<uint32_t>   fTypefaces;
    SkTIndexSet<SkFlattenable::Factory> fFactories;
};


class SkPipeCanvas : public SkCanvasVirtualEnforcer<SkNoDrawCanvas> {
public:
    SkPipeCanvas(const SkRect& cull, SkPipeDeduper*, SkWStream*);
    ~SkPipeCanvas() override;

protected:
    void willSave() override;
    SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
    void willRestore() override;

    void didConcat(const SkMatrix&) override;
    void didSetMatrix(const SkMatrix&) override;

    void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
                   const SkPaint&) override;
    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
                     int count, SkBlendMode, const SkRect* cull, const SkPaint*) override;
    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                    const SkPaint&) override;
    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
                       const SkPaint&) override;
    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                        SkScalar constY, const SkPaint&) override;
    void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkMatrix*,
                          const SkPaint&) override;
    void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint&) override;
    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
                           const SkRect* cull, const SkPaint& paint) override;
    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
                     SkBlendMode, const SkPaint&) override;

    void onDrawPaint(const SkPaint&) override;
    void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
    void onDrawRect(const SkRect&, const SkPaint&) override;
    void onDrawOval(const SkRect&, const SkPaint&) override;
    void onDrawRegion(const SkRegion&, const SkPaint&) override;
    void onDrawRRect(const SkRRect&, const SkPaint&) override;
    void onDrawPath(const SkPath&, const SkPaint&) override;
    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;

    void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
    void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
                         const SkPaint*, SrcRectConstraint) override;
    void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
                         const SkPaint*) override;
    void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
                            const SkPaint*) override;
    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;

    void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
    void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
    void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
    void onClipRegion(const SkRegion&, SkClipOp) override;

    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
    void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
    void onDrawDrawable(SkDrawable*, const SkMatrix*) override;

    // These we turn into images
    void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
    void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
                          SrcRectConstraint) override;
    void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
                          const SkPaint*) override;
    void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
                             const SkPaint*) override;

private:
    SkPipeDeduper*  fDeduper;
    SkWStream*      fStream;

    friend class SkPipeWriter;

    typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED;
};


#endif
