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

/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "SkCodecAnimation.h"
#include "SkCodecPriv.h"
#include "SkColorData.h"
#include "SkColorTable.h"
#include "SkGifCodec.h"
#include "SkMakeUnique.h"
#include "SkStream.h"
#include "SkSwizzler.h"

#include <algorithm>

#define GIF87_STAMP "GIF87a"
#define GIF89_STAMP "GIF89a"
#define GIF_STAMP_LEN 6

/*
 * Checks the start of the stream to see if the image is a gif
 */
bool SkGifCodec::IsGif(const void* buf, size_t bytesRead) {
    if (bytesRead >= GIF_STAMP_LEN) {
        if (memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
            memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0)
        {
            return true;
        }
    }
    return false;
}

/*
 * Error function
 */
static SkCodec::Result gif_error(const char* msg, SkCodec::Result result = SkCodec::kInvalidInput) {
    SkCodecPrintf("Gif Error: %s\n", msg);
    return result;
}

std::unique_ptr<SkCodec> SkGifCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
                                                    Result* result) {
    std::unique_ptr<SkGifImageReader> reader(new SkGifImageReader(std::move(stream)));
    *result = reader->parse(SkGifImageReader::SkGIFSizeQuery);
    if (*result != kSuccess) {
        return nullptr;
    }

    // If no images are in the data, or the first header is not yet defined, we cannot
    // create a codec. In either case, the width and height are not yet known.
    auto* frame = reader->frameContext(0);
    if (!frame || !frame->isHeaderDefined()) {
        *result = kInvalidInput;
        return nullptr;
    }

    // isHeaderDefined() will not return true if the screen size is empty.
    SkASSERT(reader->screenHeight() > 0 && reader->screenWidth() > 0);

    const auto alpha = reader->firstFrameHasAlpha() ? SkEncodedInfo::kBinary_Alpha
                                                    : SkEncodedInfo::kOpaque_Alpha;
    // Use kPalette since Gifs are encoded with a color table.
    // FIXME: Gifs can actually be encoded with 4-bits per pixel. Using 8 works, but we could skip
    //        expanding to 8 bits and take advantage of the SkSwizzler to work from 4.
    const auto encodedInfo = SkEncodedInfo::Make(SkEncodedInfo::kPalette_Color, alpha, 8);

    // The choice of unpremul versus premul is arbitrary, since all colors are either fully
    // opaque or fully transparent (i.e. kBinary), but we stored the transparent colors as all
    // zeroes, which is arguably premultiplied.
    const auto alphaType = reader->firstFrameHasAlpha() ? kUnpremul_SkAlphaType
                                                        : kOpaque_SkAlphaType;

    const auto imageInfo = SkImageInfo::Make(reader->screenWidth(), reader->screenHeight(),
                                             kN32_SkColorType, alphaType,
                                             SkColorSpace::MakeSRGB());
    return std::unique_ptr<SkCodec>(new SkGifCodec(encodedInfo, imageInfo, reader.release()));
}

bool SkGifCodec::onRewind() {
    fReader->clearDecodeState();
    return true;
}

SkGifCodec::SkGifCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
                       SkGifImageReader* reader)
    : INHERITED(encodedInfo, imageInfo, SkColorSpaceXform::kRGBA_8888_ColorFormat, nullptr)
    , fReader(reader)
    , fTmpBuffer(nullptr)
    , fSwizzler(nullptr)
    , fCurrColorTable(nullptr)
    , fCurrColorTableIsReal(false)
    , fFilledBackground(false)
    , fFirstCallToIncrementalDecode(false)
    , fDst(nullptr)
    , fDstRowBytes(0)
    , fRowsDecoded(0)
{
    reader->setClient(this);
}

int SkGifCodec::onGetFrameCount() {
    fReader->parse(SkGifImageReader::SkGIFFrameCountQuery);
    return fReader->imagesCount();
}

bool SkGifCodec::onGetFrameInfo(int i, SkCodec::FrameInfo* frameInfo) const {
    if (i >= fReader->imagesCount()) {
        return false;
    }

    const SkGIFFrameContext* frameContext = fReader->frameContext(i);
    SkASSERT(frameContext->reachedStartOfData());

    if (frameInfo) {
        frameInfo->fDuration = frameContext->getDuration();
        frameInfo->fRequiredFrame = frameContext->getRequiredFrame();
        frameInfo->fFullyReceived = frameContext->isComplete();
        frameInfo->fAlphaType = frameContext->hasAlpha() ? kUnpremul_SkAlphaType
                                                         : kOpaque_SkAlphaType;
        frameInfo->fDisposalMethod = frameContext->getDisposalMethod();
    }
    return true;
}

int SkGifCodec::onGetRepetitionCount() {
    fReader->parse(SkGifImageReader::SkGIFLoopCountQuery);
    return fReader->loopCount();
}

static constexpr SkColorType kXformSrcColorType = kRGBA_8888_SkColorType;
static constexpr SkAlphaType kXformAlphaType    = kUnpremul_SkAlphaType;

void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, int frameIndex) {
    SkColorType colorTableColorType = dstInfo.colorType();
    if (this->colorXform()) {
        colorTableColorType = kXformSrcColorType;
    }

    sk_sp<SkColorTable> currColorTable = fReader->getColorTable(colorTableColorType, frameIndex);
    fCurrColorTableIsReal = static_cast<bool>(currColorTable);
    if (!fCurrColorTableIsReal) {
        // This is possible for an empty frame. Create a dummy with one value (transparent).
        SkPMColor color = SK_ColorTRANSPARENT;
        fCurrColorTable.reset(new SkColorTable(&color, 1));
    } else if (this->colorXform() && !this->xformOnDecode()) {
        SkPMColor dstColors[256];
        this->applyColorXform(dstColors, currColorTable->readColors(), currColorTable->count(),
                              kXformAlphaType);
        fCurrColorTable.reset(new SkColorTable(dstColors, currColorTable->count()));
    } else {
        fCurrColorTable = std::move(currColorTable);
    }
}


SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, const Options& opts) {
    if (opts.fSubset) {
        return gif_error("Subsets not supported.\n", kUnimplemented);
    }

    const int frameIndex = opts.fFrameIndex;
    if (frameIndex > 0 && kRGB_565_SkColorType == dstInfo.colorType()) {
        // FIXME: In theory, we might be able to support this, but it's not clear that it
        // is necessary (Chromium does not decode to 565, and Android does not decode
        // frames beyond the first). Disabling it because it is somewhat difficult:
        // - If there is a transparent pixel, and this frame draws on top of another frame
        //   (if the frame is independent with a transparent pixel, we should not decode to
        //   565 anyway, since it is not opaque), we need to skip drawing the transparent
        //   pixels (see writeTransparentPixels in haveDecodedRow). We currently do this by
        //   first swizzling into temporary memory, then copying into the destination. (We
        //   let the swizzler handle it first because it may need to sample.) After
        //   swizzling to 565, we do not know which pixels in our temporary memory
        //   correspond to the transparent pixel, so we do not know what to skip. We could
        //   special case the non-sampled case (no need to swizzle), but as this is
        //   currently unused we can just not support it.
        return gif_error("Cannot decode multiframe gif (except frame 0) as 565.\n",
                         kInvalidConversion);
    }

    const auto* frame = fReader->frameContext(frameIndex);
    SkASSERT(frame);
    if (0 == frameIndex) {
        // SkCodec does not have a way to just parse through frame 0, so we
        // have to do so manually, here.
        fReader->parse((SkGifImageReader::SkGIFParseQuery) 0);
        if (!frame->reachedStartOfData()) {
            // We have parsed enough to know that there is a color map, but cannot
            // parse the map itself yet. Exit now, so we do not build an incorrect
            // table.
            return gif_error("color map not available yet\n", kIncompleteInput);
        }
    } else {
        // Parsing happened in SkCodec::getPixels.
        SkASSERT(frameIndex < fReader->imagesCount());
        SkASSERT(frame->reachedStartOfData());
    }

    if (this->xformOnDecode()) {
        fXformBuffer.reset(new uint32_t[dstInfo.width()]);
        sk_bzero(fXformBuffer.get(), dstInfo.width() * sizeof(uint32_t));
    }

    fTmpBuffer.reset(new uint8_t[dstInfo.minRowBytes()]);

    this->initializeColorTable(dstInfo, frameIndex);
    this->initializeSwizzler(dstInfo, frameIndex);

    SkASSERT(fCurrColorTable);
    return kSuccess;
}

void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex) {
    const SkGIFFrameContext* frame = fReader->frameContext(frameIndex);
    // This is only called by prepareToDecode, which ensures frameIndex is in range.
    SkASSERT(frame);

    const int xBegin = frame->xOffset();
    const int xEnd = std::min(frame->frameRect().right(), fReader->screenWidth());

    // CreateSwizzler only reads left and right of the frame. We cannot use the frame's raw
    // frameRect, since it might extend beyond the edge of the frame.
    SkIRect swizzleRect = SkIRect::MakeLTRB(xBegin, 0, xEnd, 0);

    SkImageInfo swizzlerInfo = dstInfo;
    if (this->colorXform()) {
        swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType);
        if (kPremul_SkAlphaType == dstInfo.alphaType()) {
            swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType);
        }
    }

    // The default Options should be fine:
    // - we'll ignore if the memory is zero initialized - unless we're the first frame, this won't
    //   matter anyway.
    // - subsets are not supported for gif
    // - the swizzler does not need to know about the frame.
    // We may not be able to use the real Options anyway, since getPixels does not store it (due to
    // a bug).
    fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(),
                    fCurrColorTable->readColors(), swizzlerInfo, Options(), &swizzleRect));
    SkASSERT(fSwizzler.get());
}

/*
 * Initiates the gif decode
 */
SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
                                        void* pixels, size_t dstRowBytes,
                                        const Options& opts,
                                        int* rowsDecoded) {
    Result result = this->prepareToDecode(dstInfo, opts);
    switch (result) {
        case kSuccess:
            break;
        case kIncompleteInput:
            // onStartIncrementalDecode treats this as incomplete, since it may
            // provide more data later, but in this case, no more data will be
            // provided, and there is nothing to draw. We also cannot return
            // kIncompleteInput, which will make SkCodec attempt to fill
            // remaining rows, but that requires an SkSwizzler, which we have
            // not created.
            return kInvalidInput;
        default:
            return result;
    }

    if (dstInfo.dimensions() != this->getInfo().dimensions()) {
        return gif_error("Scaling not supported.\n", kInvalidScale);
    }

    fDst = pixels;
    fDstRowBytes = dstRowBytes;

    return this->decodeFrame(true, opts, rowsDecoded);
}

SkCodec::Result SkGifCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo,
                                                     void* pixels, size_t dstRowBytes,
                                                     const SkCodec::Options& opts) {
    Result result = this->prepareToDecode(dstInfo, opts);
    if (result != kSuccess) {
        return result;
    }

    fDst = pixels;
    fDstRowBytes = dstRowBytes;

    fFirstCallToIncrementalDecode = true;

    return kSuccess;
}

SkCodec::Result SkGifCodec::onIncrementalDecode(int* rowsDecoded) {
    // It is possible the client has appended more data. Parse, if needed.
    const auto& options = this->options();
    const int frameIndex = options.fFrameIndex;
    fReader->parse((SkGifImageReader::SkGIFParseQuery) frameIndex);

    const bool firstCallToIncrementalDecode = fFirstCallToIncrementalDecode;
    fFirstCallToIncrementalDecode = false;
    return this->decodeFrame(firstCallToIncrementalDecode, options, rowsDecoded);
}

SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded) {
    const SkImageInfo& dstInfo = this->dstInfo();
    const int frameIndex = opts.fFrameIndex;
    SkASSERT(frameIndex < fReader->imagesCount());
    const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex);
    if (firstAttempt) {
        // rowsDecoded reports how many rows have been initialized, so a layer above
        // can fill the rest. In some cases, we fill the background before decoding
        // (or it is already filled for us), so we report rowsDecoded to be the full
        // height.
        bool filledBackground = false;
        if (frameContext->getRequiredFrame() == kNone) {
            // We may need to clear to transparent for one of the following reasons:
            // - The frameRect does not cover the full bounds. haveDecodedRow will
            //   only draw inside the frameRect, so we need to clear the rest.
            // - The frame is interlaced. There is no obvious way to fill
            //   afterwards for an incomplete image. (FIXME: Does the first pass
            //   cover all rows? If so, we do not have to fill here.)
            // - There is no color table for this frame. In that case will not
            //   draw anything, so we need to fill.
            if (frameContext->frameRect() != this->getInfo().bounds()
                    || frameContext->interlaced() || !fCurrColorTableIsReal) {
                // fill ignores the width (replaces it with the actual, scaled width).
                // But we need to scale in Y.
                const int scaledHeight = get_scaled_dimension(dstInfo.height(),
                                                              fSwizzler->sampleY());
                auto fillInfo = dstInfo.makeWH(0, scaledHeight);
                fSwizzler->fill(fillInfo, fDst, fDstRowBytes, this->getFillValue(dstInfo),
                                opts.fZeroInitialized);
                filledBackground = true;
            }
        } else {
            // Not independent.
            // SkCodec ensured that the prior frame has been decoded.
            filledBackground = true;
        }

        fFilledBackground = filledBackground;
        if (filledBackground) {
            // Report the full (scaled) height, since the client will never need to fill.
            fRowsDecoded = get_scaled_dimension(dstInfo.height(), fSwizzler->sampleY());
        } else {
            // This will be updated by haveDecodedRow.
            fRowsDecoded = 0;
        }
    }

    if (!fCurrColorTableIsReal) {
        // Nothing to draw this frame.
        return kSuccess;
    }

    bool frameDecoded = false;
    const bool fatalError = !fReader->decode(frameIndex, &frameDecoded);
    if (fatalError || !frameDecoded) {
        if (rowsDecoded) {
            *rowsDecoded = fRowsDecoded;
        }
        if (fatalError) {
            return kErrorInInput;
        }
        return kIncompleteInput;
    }

    return kSuccess;
}

uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
    // Using transparent as the fill value matches the behavior in Chromium,
    // which ignores the background color.
    return SK_ColorTRANSPARENT;
}

void SkGifCodec::applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const {
    if (this->xformOnDecode()) {
        SkASSERT(this->colorXform());
        fSwizzler->swizzle(fXformBuffer.get(), src);

        const int xformWidth = get_scaled_dimension(dstInfo.width(), fSwizzler->sampleX());
        this->applyColorXform(dst, fXformBuffer.get(), xformWidth, kXformAlphaType);
    } else {
        fSwizzler->swizzle(dst, src);
    }
}

template <typename T>
static void blend_line(void* dstAsVoid, const void* srcAsVoid, int width) {
    T*       dst = reinterpret_cast<T*>(dstAsVoid);
    const T* src = reinterpret_cast<const T*>(srcAsVoid);
    while (width --> 0) {
        if (*src != 0) {   // GIF pixels are either transparent (== 0) or opaque (!= 0).
            *dst = *src;
        }
        src++;
        dst++;
    }
}

void SkGifCodec::haveDecodedRow(int frameIndex, const unsigned char* rowBegin,
                                int rowNumber, int repeatCount, bool writeTransparentPixels)
{
    const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex);
    // The pixel data and coordinates supplied to us are relative to the frame's
    // origin within the entire image size, i.e.
    // (frameContext->xOffset, frameContext->yOffset). There is no guarantee
    // that width == (size().width() - frameContext->xOffset), so
    // we must ensure we don't run off the end of either the source data or the
    // row's X-coordinates.
    const int width = frameContext->width();
    const int xBegin = frameContext->xOffset();
    const int yBegin = frameContext->yOffset() + rowNumber;
    const int xEnd = std::min(xBegin + width, this->getInfo().width());
    const int yEnd = std::min(yBegin + rowNumber + repeatCount, this->getInfo().height());
    // FIXME: No need to make the checks on width/xBegin/xEnd for every row. We could instead do
    // this once in prepareToDecode.
    if (!width || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin))
        return;

    // yBegin is the first row in the non-sampled image. dstRow will be the row in the output,
    // after potentially scaling it.
    int dstRow = yBegin;

    const int sampleY = fSwizzler->sampleY();
    if (sampleY > 1) {
        // Check to see whether this row or one that falls in the repeatCount is needed in the
        // output.
        bool foundNecessaryRow = false;
        for (int i = 0; i < repeatCount; i++) {
            const int potentialRow = yBegin + i;
            if (fSwizzler->rowNeeded(potentialRow)) {
                dstRow = potentialRow / sampleY;
                const int scaledHeight = get_scaled_dimension(this->dstInfo().height(), sampleY);
                if (dstRow >= scaledHeight) {
                    return;
                }

                foundNecessaryRow = true;
                repeatCount -= i;

                repeatCount = (repeatCount - 1) / sampleY + 1;

                // Make sure the repeatCount does not take us beyond the end of the dst
                if (dstRow + repeatCount > scaledHeight) {
                    repeatCount = scaledHeight - dstRow;
                    SkASSERT(repeatCount >= 1);
                }
                break;
            }
        }

        if (!foundNecessaryRow) {
            return;
        }
    } else {
        // Make sure the repeatCount does not take us beyond the end of the dst
        SkASSERT(this->dstInfo().height() >= yBegin);
        repeatCount = SkTMin(repeatCount, this->dstInfo().height() - yBegin);
    }

    if (!fFilledBackground) {
        // At this point, we are definitely going to write the row, so count it towards the number
        // of rows decoded.
        // We do not consider the repeatCount, which only happens for interlaced, in which case we
        // have already set fRowsDecoded to the proper value (reflecting that we have filled the
        // background).
        fRowsDecoded++;
    }

    // decodeFrame will early exit if this is false, so this method will not be
    // called.
    SkASSERT(fCurrColorTableIsReal);

    // The swizzler takes care of offsetting into the dst width-wise.
    void* dstLine = SkTAddOffset<void>(fDst, dstRow * fDstRowBytes);

    // We may or may not need to write transparent pixels to the buffer.
    // If we're compositing against a previous image, it's wrong, but if
    // we're decoding an interlaced gif and displaying it "Haeberli"-style,
    // we must write these for passes beyond the first, or the initial passes
    // will "show through" the later ones.
    const auto dstInfo = this->dstInfo();
    if (writeTransparentPixels) {
        this->applyXformRow(dstInfo, dstLine, rowBegin);
    } else {
        this->applyXformRow(dstInfo, fTmpBuffer.get(), rowBegin);

        size_t offsetBytes = fSwizzler->swizzleOffsetBytes();
        if (dstInfo.colorType() == kRGBA_F16_SkColorType) {
            // Account for the fact that post-swizzling we converted to F16,
            // which is twice as wide.
            offsetBytes *= 2;
        }
        const void* src = SkTAddOffset<void>(fTmpBuffer.get(), offsetBytes);
        void*       dst = SkTAddOffset<void>(dstLine, offsetBytes);

        switch (dstInfo.colorType()) {
            case kBGRA_8888_SkColorType:
            case kRGBA_8888_SkColorType:
                blend_line<uint32_t>(dst, src, fSwizzler->swizzleWidth());
                break;
            case kRGBA_F16_SkColorType:
                blend_line<uint64_t>(dst, src, fSwizzler->swizzleWidth());
                break;
            default:
                SkASSERT(false);
                return;
        }
    }

    // Tell the frame to copy the row data if need be.
    if (repeatCount > 1) {
        const size_t bytesPerPixel = SkColorTypeBytesPerPixel(this->dstInfo().colorType());
        const size_t bytesToCopy = fSwizzler->swizzleWidth() * bytesPerPixel;
        void* copiedLine = SkTAddOffset<void>(dstLine, fSwizzler->swizzleOffsetBytes());
        void* dst = copiedLine;
        for (int i = 1; i < repeatCount; i++) {
            dst = SkTAddOffset<void>(dst, fDstRowBytes);
            memcpy(dst, copiedLine, bytesToCopy);
        }
    }
}
