105245900bf6d49068b1668da1b38890a41e09bc5scroggo/*
205245900bf6d49068b1668da1b38890a41e09bc5scroggo * Copyright 2015 Google Inc.
305245900bf6d49068b1668da1b38890a41e09bc5scroggo *
405245900bf6d49068b1668da1b38890a41e09bc5scroggo * Use of this source code is governed by a BSD-style license that can be
505245900bf6d49068b1668da1b38890a41e09bc5scroggo * found in the LICENSE file.
605245900bf6d49068b1668da1b38890a41e09bc5scroggo */
705245900bf6d49068b1668da1b38890a41e09bc5scroggo
805245900bf6d49068b1668da1b38890a41e09bc5scroggo#ifndef SkScanlineDecoder_DEFINED
905245900bf6d49068b1668da1b38890a41e09bc5scroggo#define SkScanlineDecoder_DEFINED
1005245900bf6d49068b1668da1b38890a41e09bc5scroggo
1105245900bf6d49068b1668da1b38890a41e09bc5scroggo#include "SkTypes.h"
1205245900bf6d49068b1668da1b38890a41e09bc5scroggo#include "SkTemplates.h"
1305245900bf6d49068b1668da1b38890a41e09bc5scroggo#include "SkImageGenerator.h"
1405245900bf6d49068b1668da1b38890a41e09bc5scroggo#include "SkImageInfo.h"
1505245900bf6d49068b1668da1b38890a41e09bc5scroggo
1605245900bf6d49068b1668da1b38890a41e09bc5scroggoclass SkScanlineDecoder : public SkNoncopyable {
1705245900bf6d49068b1668da1b38890a41e09bc5scroggopublic:
1805245900bf6d49068b1668da1b38890a41e09bc5scroggo    // Note for implementations: An SkScanlineDecoder will be deleted by (and
1905245900bf6d49068b1668da1b38890a41e09bc5scroggo    // therefore *before*) its associated SkCodec, in case the order matters.
2005245900bf6d49068b1668da1b38890a41e09bc5scroggo    virtual ~SkScanlineDecoder() {}
2105245900bf6d49068b1668da1b38890a41e09bc5scroggo
2205245900bf6d49068b1668da1b38890a41e09bc5scroggo    /**
2305245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  Write the next countLines scanlines into dst.
2405245900bf6d49068b1668da1b38890a41e09bc5scroggo     *
2505245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  @param dst Must be non-null, and large enough to hold countLines
2605245900bf6d49068b1668da1b38890a41e09bc5scroggo     *      scanlines of size rowBytes.
2705245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  @param countLines Number of lines to write.
2805245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  @param rowBytes Number of bytes per row. Must be large enough to hold
2905245900bf6d49068b1668da1b38890a41e09bc5scroggo     *      a scanline based on the SkImageInfo used to create this object.
3005245900bf6d49068b1668da1b38890a41e09bc5scroggo     */
3105245900bf6d49068b1668da1b38890a41e09bc5scroggo    SkImageGenerator::Result getScanlines(void* dst, int countLines, size_t rowBytes) {
3205245900bf6d49068b1668da1b38890a41e09bc5scroggo        if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0
3305245900bf6d49068b1668da1b38890a41e09bc5scroggo                || fCurrScanline + countLines > fDstInfo.height()) {
3405245900bf6d49068b1668da1b38890a41e09bc5scroggo            return SkImageGenerator::kInvalidParameters;
3505245900bf6d49068b1668da1b38890a41e09bc5scroggo        }
3605245900bf6d49068b1668da1b38890a41e09bc5scroggo        const SkImageGenerator::Result result = this->onGetScanlines(dst, countLines, rowBytes);
3705245900bf6d49068b1668da1b38890a41e09bc5scroggo        this->checkForFinish(countLines);
3805245900bf6d49068b1668da1b38890a41e09bc5scroggo        return result;
3905245900bf6d49068b1668da1b38890a41e09bc5scroggo    }
4005245900bf6d49068b1668da1b38890a41e09bc5scroggo
4105245900bf6d49068b1668da1b38890a41e09bc5scroggo    /**
4205245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  Skip count scanlines.
4305245900bf6d49068b1668da1b38890a41e09bc5scroggo     *
4405245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  The default version just calls onGetScanlines and discards the dst.
4505245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  NOTE: If skipped lines are the only lines with alpha, this default
4605245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  will make reallyHasAlpha return true, when it could have returned
4705245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  false.
4805245900bf6d49068b1668da1b38890a41e09bc5scroggo     */
4905245900bf6d49068b1668da1b38890a41e09bc5scroggo    SkImageGenerator::Result skipScanlines(int countLines) {
5005245900bf6d49068b1668da1b38890a41e09bc5scroggo        if (fCurrScanline + countLines > fDstInfo.height()) {
5105245900bf6d49068b1668da1b38890a41e09bc5scroggo            // Arguably, we could just skip the scanlines which are remaining,
5205245900bf6d49068b1668da1b38890a41e09bc5scroggo            // and return kSuccess. We choose to return invalid so the client
5305245900bf6d49068b1668da1b38890a41e09bc5scroggo            // can catch their bug.
5405245900bf6d49068b1668da1b38890a41e09bc5scroggo            return SkImageGenerator::kInvalidParameters;
5505245900bf6d49068b1668da1b38890a41e09bc5scroggo        }
5605245900bf6d49068b1668da1b38890a41e09bc5scroggo        const SkImageGenerator::Result result = this->onSkipScanlines(countLines);
5705245900bf6d49068b1668da1b38890a41e09bc5scroggo        this->checkForFinish(countLines);
5805245900bf6d49068b1668da1b38890a41e09bc5scroggo        return result;
5905245900bf6d49068b1668da1b38890a41e09bc5scroggo    }
6005245900bf6d49068b1668da1b38890a41e09bc5scroggo
6105245900bf6d49068b1668da1b38890a41e09bc5scroggo    /**
6205245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  Some images may initially report that they have alpha due to the format
6305245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  of the encoded data, but then never use any colors which have alpha
6405245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  less than 100%. This function can be called *after* decoding to
6505245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  determine if such an image truly had alpha. Calling it before decoding
6605245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  is undefined.
6705245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  FIXME: see skbug.com/3582.
6805245900bf6d49068b1668da1b38890a41e09bc5scroggo     */
6905245900bf6d49068b1668da1b38890a41e09bc5scroggo    bool reallyHasAlpha() const {
7005245900bf6d49068b1668da1b38890a41e09bc5scroggo        return this->onReallyHasAlpha();
7105245900bf6d49068b1668da1b38890a41e09bc5scroggo    }
7205245900bf6d49068b1668da1b38890a41e09bc5scroggo
7305245900bf6d49068b1668da1b38890a41e09bc5scroggoprotected:
7405245900bf6d49068b1668da1b38890a41e09bc5scroggo    SkScanlineDecoder(const SkImageInfo& requested)
7505245900bf6d49068b1668da1b38890a41e09bc5scroggo        : fDstInfo(requested)
7605245900bf6d49068b1668da1b38890a41e09bc5scroggo        , fCurrScanline(0) {}
7705245900bf6d49068b1668da1b38890a41e09bc5scroggo
7805245900bf6d49068b1668da1b38890a41e09bc5scroggo    virtual bool onReallyHasAlpha() const { return false; }
7905245900bf6d49068b1668da1b38890a41e09bc5scroggo
8097fdea6c4393cf0102d7eee5790782509fb4f57bmsarett    const SkImageInfo& dstInfo() const { return fDstInfo; }
8197fdea6c4393cf0102d7eee5790782509fb4f57bmsarett
8205245900bf6d49068b1668da1b38890a41e09bc5scroggoprivate:
8305245900bf6d49068b1668da1b38890a41e09bc5scroggo    const SkImageInfo   fDstInfo;
8405245900bf6d49068b1668da1b38890a41e09bc5scroggo    int                 fCurrScanline;
8505245900bf6d49068b1668da1b38890a41e09bc5scroggo
8605245900bf6d49068b1668da1b38890a41e09bc5scroggo    // Naive default version just calls onGetScanlines on temp memory.
8705245900bf6d49068b1668da1b38890a41e09bc5scroggo    virtual SkImageGenerator::Result onSkipScanlines(int countLines) {
8805245900bf6d49068b1668da1b38890a41e09bc5scroggo        SkAutoMalloc storage(fDstInfo.minRowBytes());
8905245900bf6d49068b1668da1b38890a41e09bc5scroggo        // Note that we pass 0 to rowBytes so we continue to use the same memory.
9005245900bf6d49068b1668da1b38890a41e09bc5scroggo        // Also note that while getScanlines checks that rowBytes is big enough,
9105245900bf6d49068b1668da1b38890a41e09bc5scroggo        // onGetScanlines bypasses that check.
9205245900bf6d49068b1668da1b38890a41e09bc5scroggo        // Calling the virtual method also means we do not double count
9305245900bf6d49068b1668da1b38890a41e09bc5scroggo        // countLines.
9405245900bf6d49068b1668da1b38890a41e09bc5scroggo        return this->onGetScanlines(storage.get(), countLines, 0);
9505245900bf6d49068b1668da1b38890a41e09bc5scroggo    }
9605245900bf6d49068b1668da1b38890a41e09bc5scroggo
9705245900bf6d49068b1668da1b38890a41e09bc5scroggo    virtual SkImageGenerator::Result onGetScanlines(void* dst, int countLines,
9805245900bf6d49068b1668da1b38890a41e09bc5scroggo                                                    size_t rowBytes) = 0;
9905245900bf6d49068b1668da1b38890a41e09bc5scroggo
10005245900bf6d49068b1668da1b38890a41e09bc5scroggo    /**
10105245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  Called after any set of scanlines read/skipped. Updates fCurrScanline,
10205245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  and, if we are at the end, calls onFinish().
10305245900bf6d49068b1668da1b38890a41e09bc5scroggo     */
10405245900bf6d49068b1668da1b38890a41e09bc5scroggo    void checkForFinish(int countLines) {
10505245900bf6d49068b1668da1b38890a41e09bc5scroggo        fCurrScanline += countLines;
10605245900bf6d49068b1668da1b38890a41e09bc5scroggo        if (fCurrScanline >= fDstInfo.height()) {
10705245900bf6d49068b1668da1b38890a41e09bc5scroggo            this->onFinish();
10805245900bf6d49068b1668da1b38890a41e09bc5scroggo        }
10905245900bf6d49068b1668da1b38890a41e09bc5scroggo    }
11005245900bf6d49068b1668da1b38890a41e09bc5scroggo
11105245900bf6d49068b1668da1b38890a41e09bc5scroggo    /**
11205245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  This function will be called after reading/skipping all scanlines to do
11305245900bf6d49068b1668da1b38890a41e09bc5scroggo     *  any necessary cleanups.
11405245900bf6d49068b1668da1b38890a41e09bc5scroggo     */
11505245900bf6d49068b1668da1b38890a41e09bc5scroggo    virtual void onFinish() {} // Default does nothing.
11605245900bf6d49068b1668da1b38890a41e09bc5scroggo};
11705245900bf6d49068b1668da1b38890a41e09bc5scroggo#endif // SkScanlineDecoder_DEFINED
118