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

#include "src/codec/SkBmpCodec.h"

#include "include/codec/SkBmpDecoder.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/private/SkEncodedInfo.h"
#include "include/private/base/SkAlign.h"
#include "src/codec/SkBmpMaskCodec.h"
#include "src/codec/SkBmpRLECodec.h"
#include "src/codec/SkBmpStandardCodec.h"
#include "src/codec/SkCodecPriv.h"
#include "src/core/SkMasks.h"

#include <cstring>
#include <memory>
#include <utility>

/*
 * Defines the version and type of the second bitmap header
 */
enum BmpHeaderType {
    kInfoV1_BmpHeaderType,
    kInfoV2_BmpHeaderType,
    kInfoV3_BmpHeaderType,
    kInfoV4_BmpHeaderType,
    kInfoV5_BmpHeaderType,
    kOS2V1_BmpHeaderType,
    kOS2VX_BmpHeaderType,
    kUnknown_BmpHeaderType
};

/*
 * Possible bitmap compression types
 */
enum BmpCompressionMethod {
    kNone_BmpCompressionMethod =          0,
    k8BitRLE_BmpCompressionMethod =       1,
    k4BitRLE_BmpCompressionMethod =       2,
    kBitMasks_BmpCompressionMethod =      3,
    kJpeg_BmpCompressionMethod =          4,
    kPng_BmpCompressionMethod =           5,
    kAlphaBitMasks_BmpCompressionMethod = 6,
    kCMYK_BmpCompressionMethod =          11,
    kCMYK8BitRLE_BmpCompressionMethod =   12,
    kCMYK4BitRLE_BmpCompressionMethod =   13
};

/*
 * Used to define the input format of the bmp
 */
enum BmpInputFormat {
    kStandard_BmpInputFormat,
    kRLE_BmpInputFormat,
    kBitMask_BmpInputFormat,
    kUnknown_BmpInputFormat
};

/*
 * Checks the start of the stream to see if the image is a bitmap
 */
bool SkBmpCodec::IsBmp(const void* buffer, size_t bytesRead) {
    // TODO: Support "IC", "PT", "CI", "CP", "BA"
    const char bmpSig[] = { 'B', 'M' };
    return bytesRead >= sizeof(bmpSig) && !memcmp(buffer, bmpSig, sizeof(bmpSig));
}

/*
 * Assumes IsBmp was called and returned true
 * Creates a bmp decoder
 * Reads enough of the stream to determine the image format
 */
std::unique_ptr<SkCodec> SkBmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
                                                    Result* result) {
    return SkBmpCodec::MakeFromStream(std::move(stream), result, false);
}

/*
 * Creates a bmp decoder for a bmp embedded in ico
 * Reads enough of the stream to determine the image format
 */
std::unique_ptr<SkCodec> SkBmpCodec::MakeFromIco(std::unique_ptr<SkStream> stream, Result* result) {
    return SkBmpCodec::MakeFromStream(std::move(stream), result, true);
}

// Header size constants
static constexpr uint32_t kBmpHeaderBytes = 14;
static constexpr uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
static constexpr uint32_t kBmpOS2V1Bytes = 12;
static constexpr uint32_t kBmpOS2V2Bytes = 64;
static constexpr uint32_t kBmpInfoBaseBytes = 16;
static constexpr uint32_t kBmpInfoV1Bytes = 40;
static constexpr uint32_t kBmpInfoV2Bytes = 52;
static constexpr uint32_t kBmpInfoV3Bytes = 56;
static constexpr uint32_t kBmpInfoV4Bytes = 108;
static constexpr uint32_t kBmpInfoV5Bytes = 124;
static constexpr uint32_t kBmpMaskBytes = 12;

static BmpHeaderType get_header_type(size_t infoBytes) {
    if (infoBytes >= kBmpInfoBaseBytes) {
        // Check the version of the header
        switch (infoBytes) {
            case kBmpInfoV1Bytes:
                return kInfoV1_BmpHeaderType;
            case kBmpInfoV2Bytes:
                return kInfoV2_BmpHeaderType;
            case kBmpInfoV3Bytes:
                return kInfoV3_BmpHeaderType;
            case kBmpInfoV4Bytes:
                return kInfoV4_BmpHeaderType;
            case kBmpInfoV5Bytes:
                return kInfoV5_BmpHeaderType;
            case 16:
            case 20:
            case 24:
            case 28:
            case 32:
            case 36:
            case 42:
            case 46:
            case 48:
            case 60:
            case kBmpOS2V2Bytes:
                return kOS2VX_BmpHeaderType;
            default:
                SkCodecPrintf("Error: unknown bmp header format.\n");
                return kUnknown_BmpHeaderType;
        }
    } if (infoBytes >= kBmpOS2V1Bytes) {
        // The OS2V1 is treated separately because it has a unique format
        return kOS2V1_BmpHeaderType;
    } else {
        // There are no valid bmp headers
        SkCodecPrintf("Error: second bitmap header size is invalid.\n");
        return kUnknown_BmpHeaderType;
    }
}

SkCodec::Result SkBmpCodec::ReadHeader(SkStream* stream, bool inIco,
        std::unique_ptr<SkCodec>* codecOut) {
    // The total bytes in the bmp file
    // We only need to use this value for RLE decoding, so we will only
    // check that it is valid in the RLE case.
    uint32_t totalBytes;
    // The offset from the start of the file where the pixel data begins
    uint32_t offset;
    // The size of the second (info) header in bytes
    uint32_t infoBytes;

    // Bmps embedded in Icos skip the first Bmp header
    if (!inIco) {
        // Read the first header and the size of the second header
        uint8_t hBuffer[kBmpHeaderBytesPlusFour];
        if (stream->read(hBuffer, kBmpHeaderBytesPlusFour) !=
                kBmpHeaderBytesPlusFour) {
            SkCodecPrintf("Error: unable to read first bitmap header.\n");
            return kIncompleteInput;
        }

        totalBytes = SkCodecPriv::UnsafeGetInt(hBuffer, 2);
        offset = SkCodecPriv::UnsafeGetInt(hBuffer, 10);
        if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
            SkCodecPrintf("Error: invalid starting location for pixel data\n");
            return kInvalidInput;
        }

        // The size of the second (info) header in bytes
        // The size is the first field of the second header, so we have already
        // read the first four infoBytes.
        infoBytes = SkCodecPriv::UnsafeGetInt(hBuffer, 14);
        if (infoBytes < kBmpOS2V1Bytes) {
            SkCodecPrintf("Error: invalid second header size.\n");
            return kInvalidInput;
        }
    } else {
        // This value is only used by RLE compression.  Bmp in Ico files do not
        // use RLE.  If the compression field is incorrectly signaled as RLE,
        // we will catch this and signal an error below.
        totalBytes = 0;

        // Bmps in Ico cannot specify an offset.  We will always assume that
        // pixel data begins immediately after the color table.  This value
        // will be corrected below.
        offset = 0;

        // Read the size of the second header
        uint8_t hBuffer[4];
        if (stream->read(hBuffer, 4) != 4) {
            SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
            return kIncompleteInput;
        }
        infoBytes = SkCodecPriv::UnsafeGetInt(hBuffer, 0);
        if (infoBytes < kBmpOS2V1Bytes) {
            SkCodecPrintf("Error: invalid second header size.\n");
            return kInvalidInput;
        }
    }

    // Determine image information depending on second header format
    const BmpHeaderType headerType = get_header_type(infoBytes);
    if (kUnknown_BmpHeaderType == headerType) {
        return kInvalidInput;
    }

    // We already read the first four bytes of the info header to get the size
    const uint32_t infoBytesRemaining = infoBytes - 4;

    // Read the second header
    std::unique_ptr<uint8_t[]> iBuffer(new uint8_t[infoBytesRemaining]);
    if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
        SkCodecPrintf("Error: unable to read second bitmap header.\n");
        return kIncompleteInput;
    }

    // The number of bits used per pixel in the pixel data
    uint16_t bitsPerPixel;

    // The compression method for the pixel data
    uint32_t compression = kNone_BmpCompressionMethod;

    // Number of colors in the color table, defaults to 0 or max (see below)
    uint32_t numColors = 0;

    // Bytes per color in the color table, early versions use 3, most use 4
    uint32_t bytesPerColor;

    // The image width and height
    int width, height;

    switch (headerType) {
        case kInfoV1_BmpHeaderType:
        case kInfoV2_BmpHeaderType:
        case kInfoV3_BmpHeaderType:
        case kInfoV4_BmpHeaderType:
        case kInfoV5_BmpHeaderType:
        case kOS2VX_BmpHeaderType:
            // We check the size of the header before entering the if statement.
            // We should not reach this point unless the size is large enough for
            // these required fields.
            SkASSERT(infoBytesRemaining >= 12);
            width = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 0);
            height = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 4);
            bitsPerPixel = SkCodecPriv::UnsafeGetShort(iBuffer.get(), 10);

            // Some versions do not have these fields, so we check before
            // overwriting the default value.
            if (infoBytesRemaining >= 16) {
                compression = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 12);
                if (infoBytesRemaining >= 32) {
                    numColors = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 28);
                }
            }

            // All of the headers that reach this point, store color table entries
            // using 4 bytes per pixel.
            bytesPerColor = 4;
            break;
        case kOS2V1_BmpHeaderType:
            // The OS2V1 is treated separately because it has a unique format
            width = (int)SkCodecPriv::UnsafeGetShort(iBuffer.get(), 0);
            height = (int)SkCodecPriv::UnsafeGetShort(iBuffer.get(), 2);
            bitsPerPixel = SkCodecPriv::UnsafeGetShort(iBuffer.get(), 6);
            bytesPerColor = 3;
            break;
        case kUnknown_BmpHeaderType:
            // We'll exit above in this case.
            SkASSERT(false);
            return kInvalidInput;
    }

    // Check for valid dimensions from header
    SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder;
    if (height < 0) {
        // We can't negate INT32_MIN.
        if (height == INT32_MIN) {
            return kInvalidInput;
        }

        height = -height;
        rowOrder = SkCodec::kTopDown_SkScanlineOrder;
    }
    // The height field for bmp in ico is double the actual height because they
    // contain an XOR mask followed by an AND mask
    if (inIco) {
        height /= 2;
    }

    // Arbitrary maximum. Matches Chromium.
    constexpr int kMaxDim = 1 << 16;
    if (width <= 0 || height <= 0 || width >= kMaxDim || height >= kMaxDim) {
        SkCodecPrintf("Error: invalid bitmap dimensions.\n");
        return kInvalidInput;
    }

    // Create mask struct
    SkMasks::InputMasks inputMasks;
    memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));

    // Determine the input compression format and set bit masks if necessary
    uint32_t maskBytes = 0;
    BmpInputFormat inputFormat = kUnknown_BmpInputFormat;
    switch (compression) {
        case kNone_BmpCompressionMethod:
            inputFormat = kStandard_BmpInputFormat;

            // In addition to more standard pixel compression formats, bmp supports
            // the use of bit masks to determine pixel components.  The standard
            // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
            // which does not map well to any Skia color formats.  For this reason,
            // we will always enable mask mode with 16 bits per pixel.
            if (16 == bitsPerPixel) {
                inputMasks.red = 0x7C00;
                inputMasks.green = 0x03E0;
                inputMasks.blue = 0x001F;
                inputFormat = kBitMask_BmpInputFormat;
            }
            break;
        case k8BitRLE_BmpCompressionMethod:
            if (bitsPerPixel != 8) {
                SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
                bitsPerPixel = 8;
            }
            inputFormat = kRLE_BmpInputFormat;
            break;
        case k4BitRLE_BmpCompressionMethod:
            if (bitsPerPixel != 4) {
                SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
                bitsPerPixel = 4;
            }
            inputFormat = kRLE_BmpInputFormat;
            break;
        case kAlphaBitMasks_BmpCompressionMethod:
        case kBitMasks_BmpCompressionMethod:
            // Load the masks
            inputFormat = kBitMask_BmpInputFormat;
            switch (headerType) {
                case kInfoV1_BmpHeaderType: {
                    // The V1 header stores the bit masks after the header
                    uint8_t buffer[kBmpMaskBytes];
                    if (stream->read(buffer, kBmpMaskBytes) != kBmpMaskBytes) {
                        SkCodecPrintf("Error: unable to read bit inputMasks.\n");
                        return kIncompleteInput;
                    }
                    maskBytes = kBmpMaskBytes;
                    inputMasks.red = SkCodecPriv::UnsafeGetInt(buffer, 0);
                    inputMasks.green = SkCodecPriv::UnsafeGetInt(buffer, 4);
                    inputMasks.blue = SkCodecPriv::UnsafeGetInt(buffer, 8);
                    break;
                }
                case kInfoV2_BmpHeaderType:
                case kInfoV3_BmpHeaderType:
                case kInfoV4_BmpHeaderType:
                case kInfoV5_BmpHeaderType:
                    // Header types are matched based on size.  If the header
                    // is V2+, we are guaranteed to be able to read at least
                    // this size.
                    SkASSERT(infoBytesRemaining >= 48);
                    inputMasks.red = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 36);
                    inputMasks.green = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 40);
                    inputMasks.blue = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 44);

                    if (kInfoV2_BmpHeaderType == headerType ||
                            (kInfoV3_BmpHeaderType == headerType && !inIco)) {
                        break;
                    }

                    // V3+ bmp files introduce an alpha mask and allow the creator of the image
                    // to use the alpha channels.  However, many of these images leave the
                    // alpha channel blank and expect to be rendered as opaque.  This is the
                    // case for almost all V3 images, so we ignore the alpha mask.  For V4+
                    // images in kMask mode, we will use the alpha mask.  Additionally, V3
                    // bmp-in-ico expect us to use the alpha mask.
                    //
                    // skbug.com/4116: We should perhaps also apply the alpha mask in kStandard
                    //                 mode.  We just haven't seen any images that expect this
                    //                 behavior.
                    //
                    // Header types are matched based on size.  If the header is
                    // V3+, we are guaranteed to be able to read at least this size.
                    SkASSERT(infoBytesRemaining >= 52);
                    inputMasks.alpha = SkCodecPriv::UnsafeGetInt(iBuffer.get(), 48);
                    break;
                case kOS2VX_BmpHeaderType:
                    // TODO: Decide if we intend to support this.
                    //       It is unsupported in the previous version and
                    //       in chromium.  I have not come across a test case
                    //       that uses this format.
                    SkCodecPrintf("Error: huffman format unsupported.\n");
                    return kUnimplemented;
                default:
                   SkCodecPrintf("Error: invalid bmp bit masks header.\n");
                   return kInvalidInput;
            }
            break;
        case kJpeg_BmpCompressionMethod:
            if (24 == bitsPerPixel) {
                inputFormat = kRLE_BmpInputFormat;
                break;
            }
            [[fallthrough]];
        case kPng_BmpCompressionMethod:
            // TODO: Decide if we intend to support this.
            //       It is unsupported in the previous version and
            //       in chromium.  I think it is used mostly for printers.
            SkCodecPrintf("Error: compression format not supported.\n");
            return kUnimplemented;
        case kCMYK_BmpCompressionMethod:
        case kCMYK8BitRLE_BmpCompressionMethod:
        case kCMYK4BitRLE_BmpCompressionMethod:
            // TODO: Same as above.
            SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
            return kUnimplemented;
        default:
            SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
            return kInvalidInput;
    }
    iBuffer.reset();

    // Calculate the number of bytes read so far
    const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
    if (!inIco && offset < bytesRead) {
        // TODO (msarett): Do we really want to fail if the offset in the header is invalid?
        //                 Seems like we can just assume that the offset is zero and try to decode?
        //                 Maybe we don't want to try to decode corrupt images?
        SkCodecPrintf("Error: pixel data offset less than header size.\n");
        return kInvalidInput;
    }



    switch (inputFormat) {
        case kStandard_BmpInputFormat: {
            // BMPs are generally opaque, however BMPs-in-ICOs may contain
            // a transparency mask after the image.  Therefore, we mark the
            // alpha as kBinary if the BMP is contained in an ICO.
            // We use |isOpaque| to indicate if the BMP itself is opaque.
            SkEncodedInfo::Alpha alpha = inIco ? SkEncodedInfo::kBinary_Alpha :
                    SkEncodedInfo::kOpaque_Alpha;
            bool isOpaque = true;

            SkEncodedInfo::Color color;
            uint8_t bitsPerComponent;
            switch (bitsPerPixel) {
                // Palette formats
                case 1:
                case 2:
                case 4:
                case 8:
                    // In the case of ICO, kBGRA is actually the closest match,
                    // since we will need to apply a transparency mask.
                    if (inIco) {
                        color = SkEncodedInfo::kBGRA_Color;
                        bitsPerComponent = 8;
                    } else {
                        color = SkEncodedInfo::kPalette_Color;
                        bitsPerComponent = (uint8_t) bitsPerPixel;
                    }
                    break;
                case 24:
                    // In the case of ICO, kBGRA is actually the closest match,
                    // since we will need to apply a transparency mask.
                    color = inIco ? SkEncodedInfo::kBGRA_Color : SkEncodedInfo::kBGR_Color;
                    bitsPerComponent = 8;
                    break;
                case 32:
                    // 32-bit BMP-in-ICOs actually use the alpha channel in place of a
                    // transparency mask.
                    if (inIco) {
                        isOpaque = false;
                        alpha = SkEncodedInfo::kUnpremul_Alpha;
                        color = SkEncodedInfo::kBGRA_Color;
                    } else {
                        color = SkEncodedInfo::kBGRX_Color;
                    }
                    bitsPerComponent = 8;
                    break;
                default:
                    SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
                    return kInvalidInput;
            }

            if (codecOut) {
                // We require streams to have a memory base for Bmp-in-Ico decodes.
                SkASSERT(!inIco || nullptr != stream->getMemoryBase());

                // Set the image info and create a codec.
                auto info = SkEncodedInfo::Make(width, height, color, alpha, bitsPerComponent);
                *codecOut = std::make_unique<SkBmpStandardCodec>(std::move(info),
                                                       std::unique_ptr<SkStream>(stream),
                                                       bitsPerPixel, numColors, bytesPerColor,
                                                       offset - bytesRead, rowOrder, isOpaque,
                                                       inIco);
                return static_cast<SkBmpStandardCodec*>(codecOut->get())->didCreateSrcBuffer()
                        ? kSuccess : kInvalidInput;
            }
            return kSuccess;
        }

        case kBitMask_BmpInputFormat: {
            // Bmp-in-Ico must be standard mode
            if (inIco) {
                SkCodecPrintf("Error: Icos may not use bit mask format.\n");
                return kInvalidInput;
            }

            switch (bitsPerPixel) {
                case 16:
                case 24:
                case 32:
                    break;
                default:
                    SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
                    return kInvalidInput;
            }

            // Skip to the start of the pixel array.
            // We can do this here because there is no color table to read
            // in bit mask mode.
            if (stream->skip(offset - bytesRead) != offset - bytesRead) {
                SkCodecPrintf("Error: unable to skip to image data.\n");
                return kIncompleteInput;
            }

            if (codecOut) {
                // Check that input bit masks are valid and create the masks object
                SkASSERT(bitsPerPixel % 8 == 0);
                std::unique_ptr<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel/8));
                if (nullptr == masks) {
                    SkCodecPrintf("Error: invalid input masks.\n");
                    return kInvalidInput;
                }

                // Masked bmps are not a great fit for SkEncodedInfo, since they have
                // arbitrary component orderings and bits per component.  Here we choose
                // somewhat reasonable values - it's ok that we don't match exactly
                // because SkBmpMaskCodec has its own mask swizzler anyway.
                SkEncodedInfo::Color color;
                SkEncodedInfo::Alpha alpha;
                if (masks->getAlphaMask()) {
                    color = SkEncodedInfo::kBGRA_Color;
                    alpha = SkEncodedInfo::kUnpremul_Alpha;
                } else {
                    color = SkEncodedInfo::kBGR_Color;
                    alpha = SkEncodedInfo::kOpaque_Alpha;
                }
                auto info = SkEncodedInfo::Make(width, height, color, alpha, 8);
                *codecOut = std::make_unique<SkBmpMaskCodec>(std::move(info),
                                                   std::unique_ptr<SkStream>(stream), bitsPerPixel,
                                                   masks.release(), rowOrder);
                return static_cast<SkBmpMaskCodec*>(codecOut->get())->didCreateSrcBuffer()
                        ? kSuccess : kInvalidInput;
            }
            return kSuccess;
        }

        case kRLE_BmpInputFormat: {
            // We should not reach this point without a valid value of bitsPerPixel.
            SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixel);

            // Check for a valid number of total bytes when in RLE mode
            if (totalBytes <= offset) {
                SkCodecPrintf("Error: RLE requires valid input size.\n");
                return kInvalidInput;
            }

            // Bmp-in-Ico must be standard mode
            // When inIco is true, this line cannot be reached, since we
            // require that RLE Bmps have a valid number of totalBytes, and
            // Icos skip the header that contains totalBytes.
            SkASSERT(!inIco);

            if (codecOut) {
                // RLE inputs may skip pixels, leaving them as transparent.  This
                // is uncommon, but we cannot be certain that an RLE bmp will be
                // opaque or that we will be able to represent it with a palette.
                // For that reason, we always indicate that we are kBGRA.
                auto info = SkEncodedInfo::Make(width, height, SkEncodedInfo::kBGRA_Color,
                                                SkEncodedInfo::kBinary_Alpha, 8);
                *codecOut = std::make_unique<SkBmpRLECodec>(std::move(info),
                                                  std::unique_ptr<SkStream>(stream), bitsPerPixel,
                                                  numColors, bytesPerColor, offset - bytesRead,
                                                  rowOrder);
            }
            return kSuccess;
        }
        default:
            SkASSERT(false);
            return kInvalidInput;
    }
}

/*
 * Creates a bmp decoder
 * Reads enough of the stream to determine the image format
 */
std::unique_ptr<SkCodec> SkBmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
                                                    Result* result, bool inIco) {
    SkASSERT(result);
    if (!stream) {
        *result = SkCodec::kInvalidInput;
        return nullptr;
    }
    std::unique_ptr<SkCodec> codec;
    *result = ReadHeader(stream.get(), inIco, &codec);
    if (codec) {
        // codec has taken ownership of stream, so we do not need to delete it.
        stream.release();
    }
    return kSuccess == *result ? std::move(codec) : nullptr;
}

SkBmpCodec::SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream,
        uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
    : INHERITED(std::move(info), kXformSrcColorFormat, std::move(stream))
    , fBitsPerPixel(bitsPerPixel)
    , fRowOrder(rowOrder)
    , fSrcRowBytes(SkAlign4(SkCodecPriv::ComputeRowBytes(this->dimensions().width(), fBitsPerPixel)))
    , fXformBuffer(nullptr)
{}

bool SkBmpCodec::onRewind() {
    return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr) == kSuccess;
}

int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
    if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
        return y;
    }
    SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder);
    return height - y - 1;
}

SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo,
        const SkCodec::Options& options) {
    return this->onPrepareToDecode(dstInfo, options);
}

SkCodec::Result SkBmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
        const SkCodec::Options& options) {
    return prepareToDecode(dstInfo, options);
}

int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
    // Create a new image info representing the portion of the image to decode
    SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);

    // Decode the requested rows
    return this->decodeRows(rowInfo, dst, rowBytes, this->options());
}

bool SkBmpCodec::skipRows(int count) {
    const size_t bytesToSkip = count * fSrcRowBytes;
    return this->stream()->skip(bytesToSkip) == bytesToSkip;
}

bool SkBmpCodec::onSkipScanlines(int count) {
    return this->skipRows(count);
}

namespace SkBmpDecoder {
bool IsBmp(const void* data, size_t len) {
    return SkBmpCodec::IsBmp(data, len);
}

std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext) {
    SkCodec::Result resultStorage;
    if (!outResult) {
        outResult = &resultStorage;
    }
    return SkBmpCodec::MakeFromStream(std::move(stream), outResult);
}

std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext) {
    if (!data) {
        if (outResult) {
            *outResult = SkCodec::kInvalidInput;
        }
        return nullptr;
    }
    return Decode(SkMemoryStream::Make(std::move(data)), outResult, nullptr);
}
}  // namespace SkBmpDecoder
