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

#include "include/utils/SkCanvasStateUtils.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/private/SkMalloc.h"
#include "src/core/SkDevice.h"
#include "src/core/SkWriter32.h"
#include "src/utils/SkCanvasStack.h"

#include <utility>

/*
 * WARNING: The structs below are part of a stable ABI and as such we explicitly
 * use unambigious primitives (e.g. int32_t instead of an enum).
 *
 * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN A NEW
 * NEW SUBCLASS OF SkCanvasState. SUCH CHANGES SHOULD ONLY BE MADE IF ABSOLUTELY
 * NECESSARY!
 *
 * In order to test changes, run the CanvasState tests. gyp/canvas_state_lib.gyp
 * describes how to create a library to pass to the CanvasState tests. The tests
 * should succeed when building the library with your changes and passing that to
 * the tests running in the unchanged Skia.
 */
enum RasterConfigs {
  kUnknown_RasterConfig   = 0,
  kRGB_565_RasterConfig   = 1,
  kARGB_8888_RasterConfig = 2
};
typedef int32_t RasterConfig;

enum CanvasBackends {
    kUnknown_CanvasBackend = 0,
    kRaster_CanvasBackend  = 1,
    kGPU_CanvasBackend     = 2,
    kPDF_CanvasBackend     = 3
};
typedef int32_t CanvasBackend;

struct ClipRect {
    int32_t left, top, right, bottom;
};

struct SkMCState {
    float matrix[9];
    // NOTE: this only works for non-antialiased clips
    int32_t clipRectCount;
    ClipRect* clipRects;
};

// NOTE: If you add more members, create a new subclass of SkCanvasState with a
// new CanvasState::version.
struct SkCanvasLayerState {
    CanvasBackend type;
    int32_t x, y;
    int32_t width;
    int32_t height;

    SkMCState mcState;

    union {
        struct {
            RasterConfig config; // pixel format: a value from RasterConfigs.
            uint64_t rowBytes;   // Number of bytes from start of one line to next.
            void* pixels;        // The pixels, all (height * rowBytes) of them.
        } raster;
        struct {
            int32_t textureID;
        } gpu;
    };
};

class SkCanvasState {
public:
    SkCanvasState(int32_t version, SkCanvas* canvas) {
        SkASSERT(canvas);
        this->version = version;
        width = canvas->getBaseLayerSize().width();
        height = canvas->getBaseLayerSize().height();

    }

    /**
     * The version this struct was built with.  This field must always appear
     * first in the struct so that when the versions don't match (and the
     * remaining contents and size are potentially different) we can still
     * compare the version numbers.
     */
    int32_t version;
    int32_t width;
    int32_t height;
    int32_t alignmentPadding;
};

class SkCanvasState_v1 : public SkCanvasState {
public:
    static const int32_t kVersion = 1;

    SkCanvasState_v1(SkCanvas* canvas) : INHERITED(kVersion, canvas) {
        layerCount = 0;
        layers = nullptr;
        mcState.clipRectCount = 0;
        mcState.clipRects = nullptr;
        originalCanvas = canvas;
    }

    ~SkCanvasState_v1() {
        // loop through the layers and free the data allocated to the clipRects.
        // See setup_MC_state, clipRects is only allocated when the clip isn't empty; and empty
        // is implicitly represented as clipRectCount == 0.
        for (int i = 0; i < layerCount; ++i) {
            if (layers[i].mcState.clipRectCount > 0) {
                sk_free(layers[i].mcState.clipRects);
            }
        }

        if (mcState.clipRectCount > 0) {
            sk_free(mcState.clipRects);
        }

        // layers is always allocated, even if it's with sk_malloc(0), so this is safe.
        sk_free(layers);
    }

    SkMCState mcState;

    int32_t layerCount;
    SkCanvasLayerState* layers;
private:
    SkCanvas* originalCanvas;
    using INHERITED = SkCanvasState;
};

////////////////////////////////////////////////////////////////////////////////

static void setup_MC_state(SkMCState* state, const SkMatrix& matrix, const SkIRect& clip) {
    // initialize the struct
    state->clipRectCount = 0;

    // capture the matrix
    for (int i = 0; i < 9; i++) {
        state->matrix[i] = matrix.get(i);
    }

    /*
     *  We only support a single clipRect, so we take the clip's bounds. Clients have long made
     *  this assumption anyway, so this restriction is fine.
     */
    SkSWriter32<sizeof(ClipRect)> clipWriter;

    if (!clip.isEmpty()) {
        state->clipRectCount = 1;
        state->clipRects = (ClipRect*)sk_malloc_throw(sizeof(ClipRect));
        state->clipRects->left = clip.fLeft;
        state->clipRects->top = clip.fTop;
        state->clipRects->right = clip.fRight;
        state->clipRects->bottom = clip.fBottom;
    }
}

SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) {
    SkASSERT(canvas);

    // Check the clip can be decomposed into rectangles (i.e. no soft clips).
    if (canvas->androidFramework_isClipAA()) {
        return nullptr;
    }

    std::unique_ptr<SkCanvasState_v1> canvasState(new SkCanvasState_v1(canvas));

    setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(), canvas->getDeviceClipBounds());

    // Historically, the canvas state could report multiple top-level layers because SkCanvas
    // supported unclipped layers. With that feature removed, all required information is contained
    // by the canvas' top-most device.
    SkBaseDevice* device = canvas->topDevice();
    SkASSERT(device);

    SkSWriter32<sizeof(SkCanvasLayerState)> layerWriter;
    // we currently only work for bitmap backed devices
    SkPixmap pmap;
    if (!device->accessPixels(&pmap) || 0 == pmap.width() || 0 == pmap.height()) {
        return nullptr;
    }
    // and for axis-aligned devices (so not transformed for an image filter)
    if (!device->isPixelAlignedToGlobal()) {
        return nullptr;
    }

    SkIPoint origin = device->getOrigin(); // safe since it's pixel aligned

    SkCanvasLayerState* layerState =
            (SkCanvasLayerState*) layerWriter.reserve(sizeof(SkCanvasLayerState));
    layerState->type = kRaster_CanvasBackend;
    layerState->x = origin.x();
    layerState->y = origin.y();
    layerState->width = pmap.width();
    layerState->height = pmap.height();

    switch (pmap.colorType()) {
        case kN32_SkColorType:
            layerState->raster.config = kARGB_8888_RasterConfig;
            break;
        case kRGB_565_SkColorType:
            layerState->raster.config = kRGB_565_RasterConfig;
            break;
        default:
            return nullptr;
    }
    layerState->raster.rowBytes = pmap.rowBytes();
    layerState->raster.pixels = pmap.writable_addr();

    setup_MC_state(&layerState->mcState, device->localToDevice(), device->devClipBounds());

    // allocate memory for the layers and then and copy them to the struct
    SkASSERT(layerWriter.bytesWritten() == sizeof(SkCanvasLayerState));
    canvasState->layerCount = 1;
    canvasState->layers = (SkCanvasLayerState*) sk_malloc_throw(layerWriter.bytesWritten());
    layerWriter.flatten(canvasState->layers);

    return canvasState.release();
}

////////////////////////////////////////////////////////////////////////////////

static void setup_canvas_from_MC_state(const SkMCState& state, SkCanvas* canvas) {
    // reconstruct the matrix
    SkMatrix matrix;
    for (int i = 0; i < 9; i++) {
        matrix.set(i, state.matrix[i]);
    }

    // only realy support 1 rect, so if the caller (legacy?) sent us more, we just take the bounds
    // of what they sent.
    SkIRect bounds = SkIRect::MakeEmpty();
    if (state.clipRectCount > 0) {
        bounds.setLTRB(state.clipRects[0].left,
                       state.clipRects[0].top,
                       state.clipRects[0].right,
                       state.clipRects[0].bottom);
        for (int i = 1; i < state.clipRectCount; ++i) {
            bounds.join({state.clipRects[i].left,
                         state.clipRects[i].top,
                         state.clipRects[i].right,
                         state.clipRects[i].bottom});
        }
    }

    canvas->clipRect(SkRect::Make(bounds));
    canvas->concat(matrix);
}

static std::unique_ptr<SkCanvas>
make_canvas_from_canvas_layer(const SkCanvasLayerState& layerState) {
    SkASSERT(kRaster_CanvasBackend == layerState.type);

    SkBitmap bitmap;
    SkColorType colorType =
        layerState.raster.config == kARGB_8888_RasterConfig ? kN32_SkColorType :
        layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType :
        kUnknown_SkColorType;

    if (colorType == kUnknown_SkColorType) {
        return nullptr;
    }

    bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height,
                                           colorType, kPremul_SkAlphaType),
                         layerState.raster.pixels, (size_t) layerState.raster.rowBytes);

    SkASSERT(!bitmap.empty());
    SkASSERT(!bitmap.isNull());

    std::unique_ptr<SkCanvas> canvas(new SkCanvas(bitmap));

    // setup the matrix and clip
    setup_canvas_from_MC_state(layerState.mcState, canvas.get());

    return canvas;
}

std::unique_ptr<SkCanvas> SkCanvasStateUtils::MakeFromCanvasState(const SkCanvasState* state) {
    SkASSERT(state);
    // Currently there is only one possible version.
    SkASSERT(SkCanvasState_v1::kVersion == state->version);

    const SkCanvasState_v1* state_v1 = static_cast<const SkCanvasState_v1*>(state);

    if (state_v1->layerCount < 1) {
        return nullptr;
    }

    std::unique_ptr<SkCanvasStack> canvas(new SkCanvasStack(state->width, state->height));

    // setup the matrix and clip on the n-way canvas
    setup_canvas_from_MC_state(state_v1->mcState, canvas.get());

    // Iterate over the layers and add them to the n-way canvas. New clients will only send one
    // layer since unclipped layers are no longer supported, but old canvas clients may still
    // create them.
    for (int i = state_v1->layerCount - 1; i >= 0; --i) {
        std::unique_ptr<SkCanvas> canvasLayer = make_canvas_from_canvas_layer(state_v1->layers[i]);
        if (!canvasLayer) {
            return nullptr;
        }
        canvas->pushCanvas(std::move(canvasLayer), SkIPoint::Make(state_v1->layers[i].x,
                                                                  state_v1->layers[i].y));
    }

    return std::move(canvas);
}

////////////////////////////////////////////////////////////////////////////////

void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) {
    SkASSERT(!state || SkCanvasState_v1::kVersion == state->version);
    // Upcast to the correct version of SkCanvasState. This avoids having a virtual destructor on
    // SkCanvasState. That would be strange since SkCanvasState has no other virtual functions, and
    // instead uses the field "version" to determine how to behave.
    delete static_cast<SkCanvasState_v1*>(state);
}
