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

#include "src/core/SkCanvasPriv.h"

#include "include/core/SkBlendMode.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkShader.h"
#include "include/private/base/SkAlign.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkAutoMalloc.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"
#include "src/core/SkWriter32.h"

#include <limits>
#include <utility>
#include <cstdint>

SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
                                                 const SkPaint* paint, const SkRect& bounds)
        : fCanvas(canvas)
        , fSaveCount(canvas->getSaveCount()) {
    if (paint) {
        SkRect newBounds = bounds;
        if (matrix) {
            matrix->mapRect(&newBounds);
        }
        canvas->saveLayer(&newBounds, paint);
    } else if (matrix) {
        canvas->save();
    }

    if (matrix) {
        canvas->concat(*matrix);
    }
}

SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
    fCanvas->restoreToCount(fSaveCount);
}

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

bool SkCanvasPriv::ReadLattice(SkReadBuffer& buffer, SkCanvas::Lattice* lattice) {
    lattice->fXCount = buffer.readInt();
    if (lattice->fXCount < 0) {
        return false;
    }
    lattice->fXDivs = buffer.skipT<int32_t>(lattice->fXCount);
    lattice->fYCount = buffer.readInt();
    if (lattice->fYCount < 0) {
        return false;
    }
    lattice->fYDivs = buffer.skipT<int32_t>(lattice->fYCount);
    int flagCount = buffer.readInt();
    lattice->fRectTypes = nullptr;
    lattice->fColors = nullptr;
    // flagCount was serialized as (xCount + 1) * (yCount + 1) if there were rect types and colors,
    // so if that isn't still the case the buffer is invalid.
    if (flagCount) {
        if (flagCount < 0 || (uint64_t) flagCount != ((uint64_t) lattice->fXCount + 1) *
                                                     ((uint64_t) lattice->fYCount + 1)) {
            return false;
        }
        lattice->fRectTypes = buffer.skipT<SkCanvas::Lattice::RectType>(flagCount);
        lattice->fColors = buffer.skipT<SkColor>(flagCount);
    }
    lattice->fBounds = buffer.skipT<SkIRect>();
    return buffer.isValid();
}

size_t SkCanvasPriv::WriteLattice(void* buffer, const SkCanvas::Lattice& lattice) {
    int flagCount = lattice.fRectTypes ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0;

    const size_t size = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * sizeof(int32_t) +
                        SkAlign4(flagCount * sizeof(SkCanvas::Lattice::RectType)) +
                        SkAlign4(flagCount * sizeof(SkColor)) +
                        sizeof(SkIRect);

    if (buffer) {
        SkWriter32 writer(buffer, size);
        writer.write32(lattice.fXCount);
        writer.write(lattice.fXDivs, lattice.fXCount * sizeof(uint32_t));
        writer.write32(lattice.fYCount);
        writer.write(lattice.fYDivs, lattice.fYCount * sizeof(uint32_t));
        writer.write32(flagCount);
        writer.writePad(lattice.fRectTypes, flagCount * sizeof(uint8_t));
        writer.write(lattice.fColors, flagCount * sizeof(SkColor));
        SkASSERT(lattice.fBounds);
        writer.write(lattice.fBounds, sizeof(SkIRect));
        SkASSERT(writer.bytesWritten() == size);
    }
    return size;
}

void SkCanvasPriv::WriteLattice(SkWriteBuffer& buffer, const SkCanvas::Lattice& lattice) {
    const size_t size = WriteLattice(nullptr, lattice);
    SkAutoSMalloc<1024> storage(size);
    WriteLattice(storage.get(), lattice);
    buffer.writePad32(storage.get(), size);
}

void SkCanvasPriv::GetDstClipAndMatrixCounts(const SkCanvas::ImageSetEntry set[], int count,
                                             int* totalDstClipCount, int* totalMatrixCount) {
    int dstClipCount = 0;
    int maxMatrixIndex = -1;
    for (int i = 0; i < count; ++i) {
        dstClipCount += 4 * set[i].fHasClip;
        if (set[i].fMatrixIndex > maxMatrixIndex) {
            maxMatrixIndex = set[i].fMatrixIndex;
        }
    }

    *totalDstClipCount = dstClipCount;
    *totalMatrixCount = maxMatrixIndex + 1;
}

// Attempts to convert an image filter to its equivalent color filter, which if possible, modifies
// the paint to compose the image filter's color filter into the paint's color filter slot. Returns
// true if the paint has been modified. Requires the paint to have an image filter.
bool SkCanvasPriv::ImageToColorFilter(SkPaint* paint) {
    SkASSERT(SkToBool(paint) && paint->getImageFilter());

    // An image filter logically runs after any mask filter and the src-over blending against the
    // layer's transparent black initial content. Moving the image filter (as a color filter) into
    // the color filter slot causes it to run before the mask filter or blending.
    //
    // Src-over blending against transparent black is a no-op, so skipping the layer and drawing the
    // output of the color filter-image filter with the original blender is valid.
    //
    // If there's also a mask filter on the paint, it will operate on an alpha-only layer that's
    // then shaded with the paint's effects. Moving the CF-IF into the paint's color filter slot
    // will mean that the CF-IF operates on the output of the original CF *before* it's combined
    // with the coverage value. Under normal circumstances the CF-IF evaluates the color after
    // coverage has been multiplied into the alpha channel.
    //
    // Some color filters may behave the same, e.g. cf(color)*coverage == cf(color*coverage), but
    // that's hard to detect so we disable the optimization when both image filters and mask filters
    // are present.
    if (paint->getMaskFilter()) {
        return false;
    }

    SkColorFilter* imgCFPtr;
    if (!paint->getImageFilter()->asAColorFilter(&imgCFPtr)) {
        return false;
    }
    sk_sp<SkColorFilter> imgCF(imgCFPtr);

    SkColorFilter* paintCF = paint->getColorFilter();
    if (paintCF) {
        // The paint has both a colorfilter(paintCF) and an imagefilter-that-is-a-colorfilter(imgCF)
        // and we need to combine them into a single colorfilter.
        imgCF = imgCF->makeComposed(sk_ref_sp(paintCF));
    }

    paint->setColorFilter(std::move(imgCF));
    paint->setImageFilter(nullptr);
    return true;
}

AutoLayerForImageFilter::AutoLayerForImageFilter(SkCanvas* canvas,
                                                 const SkPaint& paint,
                                                 const SkRect* rawBounds,
                                                 bool skipMaskFilterLayer)
            : fPaint(paint)
            , fCanvas(canvas)
            , fTempLayersForFilters(0) {
    SkDEBUGCODE(fSaveCount = canvas->getSaveCount();)

    // Depending on the original paint, this will add 0, 1, or 2 layers that apply the
    // filter effects to a temporary layer that rasterized the remaining effects. Image filters
    // are applied to the result of any mask filter, so its layer is added first in the stack.
    //
    // If present on the original paint, the image filter layer's restore paint steals the blender
    // and the image filter so that the draw's paint will never have an image filter.
    if (fPaint.getImageFilter() && !SkCanvasPriv::ImageToColorFilter(&fPaint)) {
        this->addImageFilterLayer(rawBounds);
    }

    // If present on the original paint, the mask filter layer's restore paint steals all shading
    // effects and the draw's paint shading is updated to draw a solid opaque color (thus encoding
    // coverage into the alpha channel). The draw's paint preserves all geometric effects that have
    // to be applied before the mask filter. The layer's restore paint adds an image filter
    // representing the mask filter.
    if (fPaint.getMaskFilter() && !skipMaskFilterLayer) {
        this->addMaskFilterLayer(rawBounds);
    }

   // When the original paint has both an image filter and a mask filter, this will create two
   // internal layers and perform two restores when finished. This actually creates one fewer
   // offscreen passes compared to directly composing the mask filter's output with an
   // SkImageFilters::Shader node and passing that into the rest of the image filter.
}

AutoLayerForImageFilter::~AutoLayerForImageFilter() {
    for (int i = 0; i < fTempLayersForFilters; ++i) {
        fCanvas->fSaveCount -= 1;
        fCanvas->internalRestore();
    }
    // Negative save count occurs when this layer was moved.
    SkASSERT(fSaveCount < 0 || fCanvas->getSaveCount() == fSaveCount);
}

AutoLayerForImageFilter::AutoLayerForImageFilter(AutoLayerForImageFilter&& other) {
    *this = std::move(other);
}

AutoLayerForImageFilter& AutoLayerForImageFilter::operator=(AutoLayerForImageFilter&& other) {
    fPaint = std::move(other.fPaint);
    fCanvas = other.fCanvas;
    fTempLayersForFilters = other.fTempLayersForFilters;
    SkDEBUGCODE(fSaveCount = other.fSaveCount;)

    other.fTempLayersForFilters = 0;
    SkDEBUGCODE(other.fSaveCount = -1;)

    return *this;
}

void AutoLayerForImageFilter::addImageFilterLayer(const SkRect* drawBounds) {
    // Shouldn't be adding a layer if there was no image filter to begin with.
    SkASSERT(fPaint.getImageFilter());

    // The restore paint for an image filter layer simply takes the image filter and blending off
    // the original paint. The blending is applied post image filter because otherwise it'd be
    // applied with the new layer's transparent dst and not be very interesting.
    SkPaint restorePaint;
    restorePaint.setImageFilter(fPaint.refImageFilter());
    restorePaint.setBlender(fPaint.refBlender());

    // Remove the restorePaint fields from our "working" paint, leaving all other shading and
    // geometry effects to be rendered into the layer. If there happens to be a mask filter, this
    // paint will still trigger a second layer for that filter.
    fPaint.setImageFilter(nullptr);
    fPaint.setBlendMode(SkBlendMode::kSrcOver);

    this->addLayer(restorePaint, drawBounds, /*coverageOnly=*/false);
}

void AutoLayerForImageFilter::addMaskFilterLayer(const SkRect* drawBounds) {
    // Shouldn't be adding a layer if there was no mask filter to begin with.
    SkASSERT(fPaint.getMaskFilter());

    // Image filters are evaluated after mask filters so any filter should have been converted to
    // a layer and removed from fPaint already.
    SkASSERT(!fPaint.getImageFilter());

    // TODO: Eventually all SkMaskFilters will implement this method so this can switch to an assert
    auto [maskFilterAsImageFilter, appliesShading] = as_MFB(
        fPaint.getMaskFilter())->asImageFilter(fCanvas->getTotalMatrix(), fPaint);
    if (!maskFilterAsImageFilter) {
        // This is a legacy mask filter that can be handled by raster and Ganesh directly, but will
        // be ignored by Graphite. Return now, leaving the paint with the mask filter so that the
        // underlying SkDevice can handle it if it will.
        return;
    }

    // The restore paint for the coverage layer takes over all shading effects that had been on the
    // original paint, which will be applied to the alpha-only output image from the mask filter
    // converted to an image filter.
    // If we know our mask filter will affect shading, we don't want to add the original shading
    // into the restore paint.
    SkPaint restorePaint;
    if (!appliesShading) {
        restorePaint.setColor4f(fPaint.getColor4f());
        restorePaint.setShader(fPaint.refShader());
        restorePaint.setColorFilter(fPaint.refColorFilter());
        restorePaint.setDither(fPaint.isDither());
    }
    restorePaint.setBlender(fPaint.refBlender());
    restorePaint.setImageFilter(maskFilterAsImageFilter);

    // Remove all shading effects from the "working" paint so that the layer's alpha channel
    // will correspond to the coverage. This leaves the original style and AA settings that
    // contribute to coverage (including any path effect).
    fPaint.setColor4f(SkColors::kWhite);
    fPaint.setShader(nullptr);
    fPaint.setColorFilter(nullptr);
    fPaint.setMaskFilter(nullptr);
    fPaint.setDither(false);
    fPaint.setBlendMode(SkBlendMode::kSrcOver);

    this->addLayer(restorePaint, drawBounds, /*coverageOnly=*/!appliesShading);
}

void AutoLayerForImageFilter::addLayer(const SkPaint& restorePaint,
                                       const SkRect* drawBounds,
                                       bool coverageOnly) {
    SkRect storage;
    const SkRect* contentBounds = nullptr;
    if (drawBounds && fPaint.canComputeFastBounds()) {
        // The content bounds will include all paint outsets except for those that have been
        // extracted into 'restorePaint' or a previously added layer.
        contentBounds = &fPaint.computeFastBounds(*drawBounds, &storage);
    }

    fCanvas->fSaveCount += 1;
    fCanvas->internalSaveLayer(SkCanvas::SaveLayerRec(contentBounds, &restorePaint),
                               SkCanvas::kFullLayer_SaveLayerStrategy,
                               coverageOnly);
    fTempLayersForFilters += 1;
}
