/*
 * 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 "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 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;

    // 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 SkNoDrawCanvas INHERITED;
};


#endif
