1741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
2741143878b23d22cd9cb7b9cba8055179115ce17msarett * Copyright 2015 Google Inc.
3741143878b23d22cd9cb7b9cba8055179115ce17msarett *
4741143878b23d22cd9cb7b9cba8055179115ce17msarett * Use of this source code is governed by a BSD-style license that can be
5741143878b23d22cd9cb7b9cba8055179115ce17msarett * found in the LICENSE file.
6741143878b23d22cd9cb7b9cba8055179115ce17msarett */
7741143878b23d22cd9cb7b9cba8055179115ce17msarett
8741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkCodec_libbmp.h"
9741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkCodecPriv.h"
10741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkColorPriv.h"
11741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkStream.h"
12741143878b23d22cd9cb7b9cba8055179115ce17msarett
13741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
14741143878b23d22cd9cb7b9cba8055179115ce17msarett *
15741143878b23d22cd9cb7b9cba8055179115ce17msarett * Checks if the conversion between the input image and the requested output
16741143878b23d22cd9cb7b9cba8055179115ce17msarett * image has been implemented
17741143878b23d22cd9cb7b9cba8055179115ce17msarett *
18741143878b23d22cd9cb7b9cba8055179115ce17msarett */
19741143878b23d22cd9cb7b9cba8055179115ce17msarettstatic bool conversion_possible(const SkImageInfo& dst,
20741143878b23d22cd9cb7b9cba8055179115ce17msarett                                const SkImageInfo& src) {
21eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Ensure that the profile type is unchanged
22eed039b5ffbdff958053ac80b09451ad6caa1787msarett    if (dst.profileType() != src.profileType()) {
23741143878b23d22cd9cb7b9cba8055179115ce17msarett        return false;
24741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
25eed039b5ffbdff958053ac80b09451ad6caa1787msarett
26438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Check for supported alpha types
27438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (src.alphaType() != dst.alphaType()) {
28438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        if (kOpaque_SkAlphaType == src.alphaType()) {
29438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // If the source is opaque, we must decode to opaque
30438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            return false;
31438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        }
32438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
33438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // The source is not opaque
34438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        switch (dst.alphaType()) {
35438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            case kPremul_SkAlphaType:
36438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            case kUnpremul_SkAlphaType:
37438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                // The source is not opaque, so either of these is okay
38438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                break;
39438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            default:
40438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                // We cannot decode a non-opaque image to opaque (or unknown)
41438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                return false;
42438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        }
43438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
44438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
45438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Check for supported color types
46eed039b5ffbdff958053ac80b09451ad6caa1787msarett    switch (dst.colorType()) {
47438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // Allow output to kN32 from any type of input
48eed039b5ffbdff958053ac80b09451ad6caa1787msarett        case kN32_SkColorType:
49438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            return true;
50438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // Allow output to kIndex_8 from compatible inputs
51438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        case kIndex_8_SkColorType:
52438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            return kIndex_8_SkColorType == src.colorType();
53eed039b5ffbdff958053ac80b09451ad6caa1787msarett        default:
54eed039b5ffbdff958053ac80b09451ad6caa1787msarett            return false;
55741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
56741143878b23d22cd9cb7b9cba8055179115ce17msarett}
57741143878b23d22cd9cb7b9cba8055179115ce17msarett
58741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
59741143878b23d22cd9cb7b9cba8055179115ce17msarett *
60741143878b23d22cd9cb7b9cba8055179115ce17msarett * Defines the version and type of the second bitmap header
61741143878b23d22cd9cb7b9cba8055179115ce17msarett *
62741143878b23d22cd9cb7b9cba8055179115ce17msarett */
63741143878b23d22cd9cb7b9cba8055179115ce17msarettenum BitmapHeaderType {
64741143878b23d22cd9cb7b9cba8055179115ce17msarett    kInfoV1_BitmapHeaderType,
65741143878b23d22cd9cb7b9cba8055179115ce17msarett    kInfoV2_BitmapHeaderType,
66741143878b23d22cd9cb7b9cba8055179115ce17msarett    kInfoV3_BitmapHeaderType,
67741143878b23d22cd9cb7b9cba8055179115ce17msarett    kInfoV4_BitmapHeaderType,
68741143878b23d22cd9cb7b9cba8055179115ce17msarett    kInfoV5_BitmapHeaderType,
69741143878b23d22cd9cb7b9cba8055179115ce17msarett    kOS2V1_BitmapHeaderType,
70741143878b23d22cd9cb7b9cba8055179115ce17msarett    kOS2VX_BitmapHeaderType,
71741143878b23d22cd9cb7b9cba8055179115ce17msarett    kUnknown_BitmapHeaderType
72741143878b23d22cd9cb7b9cba8055179115ce17msarett};
73741143878b23d22cd9cb7b9cba8055179115ce17msarett
74741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
75741143878b23d22cd9cb7b9cba8055179115ce17msarett *
76741143878b23d22cd9cb7b9cba8055179115ce17msarett * Possible bitmap compression types
77741143878b23d22cd9cb7b9cba8055179115ce17msarett *
78741143878b23d22cd9cb7b9cba8055179115ce17msarett */
79741143878b23d22cd9cb7b9cba8055179115ce17msarettenum BitmapCompressionMethod {
80741143878b23d22cd9cb7b9cba8055179115ce17msarett    kNone_BitmapCompressionMethod =          0,
81741143878b23d22cd9cb7b9cba8055179115ce17msarett    k8BitRLE_BitmapCompressionMethod =       1,
82741143878b23d22cd9cb7b9cba8055179115ce17msarett    k4BitRLE_BitmapCompressionMethod =       2,
83741143878b23d22cd9cb7b9cba8055179115ce17msarett    kBitMasks_BitmapCompressionMethod =      3,
84741143878b23d22cd9cb7b9cba8055179115ce17msarett    kJpeg_BitmapCompressionMethod =          4,
85741143878b23d22cd9cb7b9cba8055179115ce17msarett    kPng_BitmapCompressionMethod =           5,
86741143878b23d22cd9cb7b9cba8055179115ce17msarett    kAlphaBitMasks_BitmapCompressionMethod = 6,
87741143878b23d22cd9cb7b9cba8055179115ce17msarett    kCMYK_BitmapCompressionMethod =          11,
88741143878b23d22cd9cb7b9cba8055179115ce17msarett    kCMYK8BitRLE_BitmapCompressionMethod =   12,
89741143878b23d22cd9cb7b9cba8055179115ce17msarett    kCMYK4BitRLE_BitmapCompressionMethod =   13
90741143878b23d22cd9cb7b9cba8055179115ce17msarett};
91741143878b23d22cd9cb7b9cba8055179115ce17msarett
92741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
93741143878b23d22cd9cb7b9cba8055179115ce17msarett *
94741143878b23d22cd9cb7b9cba8055179115ce17msarett * Checks the start of the stream to see if the image is a bitmap
95741143878b23d22cd9cb7b9cba8055179115ce17msarett *
96741143878b23d22cd9cb7b9cba8055179115ce17msarett */
97741143878b23d22cd9cb7b9cba8055179115ce17msarettbool SkBmpCodec::IsBmp(SkStream* stream) {
98741143878b23d22cd9cb7b9cba8055179115ce17msarett    // TODO: Support "IC", "PT", "CI", "CP", "BA"
99741143878b23d22cd9cb7b9cba8055179115ce17msarett    const char bmpSig[] = { 'B', 'M' };
100741143878b23d22cd9cb7b9cba8055179115ce17msarett    char buffer[sizeof(bmpSig)];
101741143878b23d22cd9cb7b9cba8055179115ce17msarett    return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
102741143878b23d22cd9cb7b9cba8055179115ce17msarett            !memcmp(buffer, bmpSig, sizeof(bmpSig));
103741143878b23d22cd9cb7b9cba8055179115ce17msarett}
104741143878b23d22cd9cb7b9cba8055179115ce17msarett
105741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
106741143878b23d22cd9cb7b9cba8055179115ce17msarett *
107741143878b23d22cd9cb7b9cba8055179115ce17msarett * Assumes IsBmp was called and returned true
1089bde918754bc292469d801f156f3b626eb3db780msarett * Creates a bmp decoder
109741143878b23d22cd9cb7b9cba8055179115ce17msarett * Reads enough of the stream to determine the image format
110741143878b23d22cd9cb7b9cba8055179115ce17msarett *
111741143878b23d22cd9cb7b9cba8055179115ce17msarett */
112741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
1139bde918754bc292469d801f156f3b626eb3db780msarett    return SkBmpCodec::NewFromStream(stream, false);
1149bde918754bc292469d801f156f3b626eb3db780msarett}
1159bde918754bc292469d801f156f3b626eb3db780msarett
1169bde918754bc292469d801f156f3b626eb3db780msarett/*
1179bde918754bc292469d801f156f3b626eb3db780msarett *
1189bde918754bc292469d801f156f3b626eb3db780msarett * Creates a bmp decoder for a bmp embedded in ico
1199bde918754bc292469d801f156f3b626eb3db780msarett * Reads enough of the stream to determine the image format
1209bde918754bc292469d801f156f3b626eb3db780msarett *
1219bde918754bc292469d801f156f3b626eb3db780msarett */
1229bde918754bc292469d801f156f3b626eb3db780msarettSkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
1239bde918754bc292469d801f156f3b626eb3db780msarett    return SkBmpCodec::NewFromStream(stream, true);
1249bde918754bc292469d801f156f3b626eb3db780msarett}
1259bde918754bc292469d801f156f3b626eb3db780msarett
1269bde918754bc292469d801f156f3b626eb3db780msarett/*
1279bde918754bc292469d801f156f3b626eb3db780msarett *
12879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
12979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * representing success or failure. If it returned true, and codecOut was
13079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * not NULL, it will be set to a new SkBmpCodec.
1310a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo * Does *not* take ownership of the passed in SkStream.
1329bde918754bc292469d801f156f3b626eb3db780msarett *
1339bde918754bc292469d801f156f3b626eb3db780msarett */
13479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggobool SkBmpCodec::ReadHeader(SkStream* stream, bool isIco, SkCodec** codecOut) {
135741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Header size constants
136741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpHeaderBytes = 14;
137741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
138741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpOS2V1Bytes = 12;
139741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpOS2V2Bytes = 64;
140741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpInfoBaseBytes = 16;
141741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpInfoV1Bytes = 40;
142741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpInfoV2Bytes = 52;
143741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpInfoV3Bytes = 56;
144741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpInfoV4Bytes = 108;
145741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpInfoV5Bytes = 124;
146741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint32_t kBmpMaskBytes = 12;
147741143878b23d22cd9cb7b9cba8055179115ce17msarett
1487aa846c6837f527067e7ab5fdeacdbd502696382tomhudson    // The total bytes in the bmp file
1499bde918754bc292469d801f156f3b626eb3db780msarett    // We only need to use this value for RLE decoding, so we will only
1509bde918754bc292469d801f156f3b626eb3db780msarett    // check that it is valid in the RLE case.
1519bde918754bc292469d801f156f3b626eb3db780msarett    uint32_t totalBytes;
1527aa846c6837f527067e7ab5fdeacdbd502696382tomhudson    // The offset from the start of the file where the pixel data begins
1539bde918754bc292469d801f156f3b626eb3db780msarett    uint32_t offset;
1547aa846c6837f527067e7ab5fdeacdbd502696382tomhudson    // The size of the second (info) header in bytes
1559bde918754bc292469d801f156f3b626eb3db780msarett    uint32_t infoBytes;
1569bde918754bc292469d801f156f3b626eb3db780msarett
1579bde918754bc292469d801f156f3b626eb3db780msarett    // Bmps embedded in Icos skip the first Bmp header
1589bde918754bc292469d801f156f3b626eb3db780msarett    if (!isIco) {
1599bde918754bc292469d801f156f3b626eb3db780msarett        // Read the first header and the size of the second header
1609bde918754bc292469d801f156f3b626eb3db780msarett        SkAutoTDeleteArray<uint8_t> hBuffer(
1619bde918754bc292469d801f156f3b626eb3db780msarett                SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
1629bde918754bc292469d801f156f3b626eb3db780msarett        if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
1639bde918754bc292469d801f156f3b626eb3db780msarett                kBmpHeaderBytesPlusFour) {
164230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: unable to read first bitmap header.\n");
16579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
1669bde918754bc292469d801f156f3b626eb3db780msarett        }
1679bde918754bc292469d801f156f3b626eb3db780msarett
1689bde918754bc292469d801f156f3b626eb3db780msarett        totalBytes = get_int(hBuffer.get(), 2);
1699bde918754bc292469d801f156f3b626eb3db780msarett        offset = get_int(hBuffer.get(), 10);
1709bde918754bc292469d801f156f3b626eb3db780msarett        if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
171230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: invalid starting location for pixel data\n");
17279e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
1739bde918754bc292469d801f156f3b626eb3db780msarett        }
1749bde918754bc292469d801f156f3b626eb3db780msarett
1759bde918754bc292469d801f156f3b626eb3db780msarett        // The size of the second (info) header in bytes
1769bde918754bc292469d801f156f3b626eb3db780msarett        // The size is the first field of the second header, so we have already
1779bde918754bc292469d801f156f3b626eb3db780msarett        // read the first four infoBytes.
1789bde918754bc292469d801f156f3b626eb3db780msarett        infoBytes = get_int(hBuffer.get(), 14);
1799bde918754bc292469d801f156f3b626eb3db780msarett        if (infoBytes < kBmpOS2V1Bytes) {
180230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: invalid second header size.\n");
18179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
1829bde918754bc292469d801f156f3b626eb3db780msarett        }
1839bde918754bc292469d801f156f3b626eb3db780msarett    } else {
1849bde918754bc292469d801f156f3b626eb3db780msarett        // This value is only used by RLE compression.  Bmp in Ico files do not
1859bde918754bc292469d801f156f3b626eb3db780msarett        // use RLE.  If the compression field is incorrectly signaled as RLE,
1869bde918754bc292469d801f156f3b626eb3db780msarett        // we will catch this and signal an error below.
1879bde918754bc292469d801f156f3b626eb3db780msarett        totalBytes = 0;
1889bde918754bc292469d801f156f3b626eb3db780msarett
1899bde918754bc292469d801f156f3b626eb3db780msarett        // Bmps in Ico cannot specify an offset.  We will always assume that
1909bde918754bc292469d801f156f3b626eb3db780msarett        // pixel data begins immediately after the color table.  This value
1919bde918754bc292469d801f156f3b626eb3db780msarett        // will be corrected below.
1929bde918754bc292469d801f156f3b626eb3db780msarett        offset = 0;
1939bde918754bc292469d801f156f3b626eb3db780msarett
1949bde918754bc292469d801f156f3b626eb3db780msarett        // Read the size of the second header
1959bde918754bc292469d801f156f3b626eb3db780msarett        SkAutoTDeleteArray<uint8_t> hBuffer(
1969bde918754bc292469d801f156f3b626eb3db780msarett                SkNEW_ARRAY(uint8_t, 4));
1979bde918754bc292469d801f156f3b626eb3db780msarett        if (stream->read(hBuffer.get(), 4) != 4) {
198230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
19979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
2009bde918754bc292469d801f156f3b626eb3db780msarett        }
2019bde918754bc292469d801f156f3b626eb3db780msarett        infoBytes = get_int(hBuffer.get(), 0);
2029bde918754bc292469d801f156f3b626eb3db780msarett        if (infoBytes < kBmpOS2V1Bytes) {
203230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: invalid second header size.\n");
20479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
2059bde918754bc292469d801f156f3b626eb3db780msarett        }
2067aa846c6837f527067e7ab5fdeacdbd502696382tomhudson    }
2079bde918754bc292469d801f156f3b626eb3db780msarett
2089bde918754bc292469d801f156f3b626eb3db780msarett    // We already read the first four bytes of the info header to get the size
209741143878b23d22cd9cb7b9cba8055179115ce17msarett    const uint32_t infoBytesRemaining = infoBytes - 4;
210741143878b23d22cd9cb7b9cba8055179115ce17msarett
211741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Read the second header
212741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkAutoTDeleteArray<uint8_t> iBuffer(
213741143878b23d22cd9cb7b9cba8055179115ce17msarett            SkNEW_ARRAY(uint8_t, infoBytesRemaining));
214741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
215230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: unable to read second bitmap header.\n");
21679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return false;
217741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
218741143878b23d22cd9cb7b9cba8055179115ce17msarett
219741143878b23d22cd9cb7b9cba8055179115ce17msarett    // The number of bits used per pixel in the pixel data
220741143878b23d22cd9cb7b9cba8055179115ce17msarett    uint16_t bitsPerPixel;
221741143878b23d22cd9cb7b9cba8055179115ce17msarett
222741143878b23d22cd9cb7b9cba8055179115ce17msarett    // The compression method for the pixel data
223741143878b23d22cd9cb7b9cba8055179115ce17msarett    uint32_t compression = kNone_BitmapCompressionMethod;
224741143878b23d22cd9cb7b9cba8055179115ce17msarett
225741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Number of colors in the color table, defaults to 0 or max (see below)
226741143878b23d22cd9cb7b9cba8055179115ce17msarett    uint32_t numColors = 0;
227741143878b23d22cd9cb7b9cba8055179115ce17msarett
228741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Bytes per color in the color table, early versions use 3, most use 4
229741143878b23d22cd9cb7b9cba8055179115ce17msarett    uint32_t bytesPerColor;
230741143878b23d22cd9cb7b9cba8055179115ce17msarett
231741143878b23d22cd9cb7b9cba8055179115ce17msarett    // The image width and height
232741143878b23d22cd9cb7b9cba8055179115ce17msarett    int width, height;
233741143878b23d22cd9cb7b9cba8055179115ce17msarett
234741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Determine image information depending on second header format
235741143878b23d22cd9cb7b9cba8055179115ce17msarett    BitmapHeaderType headerType;
236741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (infoBytes >= kBmpInfoBaseBytes) {
237741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Check the version of the header
238741143878b23d22cd9cb7b9cba8055179115ce17msarett        switch (infoBytes) {
239741143878b23d22cd9cb7b9cba8055179115ce17msarett            case kBmpInfoV1Bytes:
240741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kInfoV1_BitmapHeaderType;
241741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
242741143878b23d22cd9cb7b9cba8055179115ce17msarett            case kBmpInfoV2Bytes:
243741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kInfoV2_BitmapHeaderType;
244741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
245741143878b23d22cd9cb7b9cba8055179115ce17msarett            case kBmpInfoV3Bytes:
246741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kInfoV3_BitmapHeaderType;
247741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
248741143878b23d22cd9cb7b9cba8055179115ce17msarett            case kBmpInfoV4Bytes:
249741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kInfoV4_BitmapHeaderType;
250741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
251741143878b23d22cd9cb7b9cba8055179115ce17msarett            case kBmpInfoV5Bytes:
252741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kInfoV5_BitmapHeaderType;
253741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
254741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 16:
255741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 20:
256741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 24:
257741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 28:
258741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 32:
259741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 36:
260741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 42:
261741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 46:
262741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 48:
263741143878b23d22cd9cb7b9cba8055179115ce17msarett            case 60:
264741143878b23d22cd9cb7b9cba8055179115ce17msarett            case kBmpOS2V2Bytes:
265741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kOS2VX_BitmapHeaderType;
266741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
267741143878b23d22cd9cb7b9cba8055179115ce17msarett            default:
268741143878b23d22cd9cb7b9cba8055179115ce17msarett                // We do not signal an error here because there is the
269741143878b23d22cd9cb7b9cba8055179115ce17msarett                // possibility of new or undocumented bmp header types.  Most
270741143878b23d22cd9cb7b9cba8055179115ce17msarett                // of the newer versions of bmp headers are similar to and
271741143878b23d22cd9cb7b9cba8055179115ce17msarett                // build off of the older versions, so we may still be able to
272741143878b23d22cd9cb7b9cba8055179115ce17msarett                // decode the bmp.
273230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                SkCodecPrintf("Warning: unknown bmp header format.\n");
274741143878b23d22cd9cb7b9cba8055179115ce17msarett                headerType = kUnknown_BitmapHeaderType;
275741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
276741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
277741143878b23d22cd9cb7b9cba8055179115ce17msarett        // We check the size of the header before entering the if statement.
278741143878b23d22cd9cb7b9cba8055179115ce17msarett        // We should not reach this point unless the size is large enough for
279741143878b23d22cd9cb7b9cba8055179115ce17msarett        // these required fields.
280741143878b23d22cd9cb7b9cba8055179115ce17msarett        SkASSERT(infoBytesRemaining >= 12);
281741143878b23d22cd9cb7b9cba8055179115ce17msarett        width = get_int(iBuffer.get(), 0);
282741143878b23d22cd9cb7b9cba8055179115ce17msarett        height = get_int(iBuffer.get(), 4);
283741143878b23d22cd9cb7b9cba8055179115ce17msarett        bitsPerPixel = get_short(iBuffer.get(), 10);
284741143878b23d22cd9cb7b9cba8055179115ce17msarett
285741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Some versions do not have these fields, so we check before
286741143878b23d22cd9cb7b9cba8055179115ce17msarett        // overwriting the default value.
287741143878b23d22cd9cb7b9cba8055179115ce17msarett        if (infoBytesRemaining >= 16) {
288741143878b23d22cd9cb7b9cba8055179115ce17msarett            compression = get_int(iBuffer.get(), 12);
289741143878b23d22cd9cb7b9cba8055179115ce17msarett            if (infoBytesRemaining >= 32) {
290741143878b23d22cd9cb7b9cba8055179115ce17msarett                numColors = get_int(iBuffer.get(), 28);
291741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
292741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
293741143878b23d22cd9cb7b9cba8055179115ce17msarett
294741143878b23d22cd9cb7b9cba8055179115ce17msarett        // All of the headers that reach this point, store color table entries
295741143878b23d22cd9cb7b9cba8055179115ce17msarett        // using 4 bytes per pixel.
296741143878b23d22cd9cb7b9cba8055179115ce17msarett        bytesPerColor = 4;
297741143878b23d22cd9cb7b9cba8055179115ce17msarett    } else if (infoBytes >= kBmpOS2V1Bytes) {
298741143878b23d22cd9cb7b9cba8055179115ce17msarett        // The OS2V1 is treated separately because it has a unique format
299741143878b23d22cd9cb7b9cba8055179115ce17msarett        headerType = kOS2V1_BitmapHeaderType;
300741143878b23d22cd9cb7b9cba8055179115ce17msarett        width = (int) get_short(iBuffer.get(), 0);
301741143878b23d22cd9cb7b9cba8055179115ce17msarett        height = (int) get_short(iBuffer.get(), 2);
302741143878b23d22cd9cb7b9cba8055179115ce17msarett        bitsPerPixel = get_short(iBuffer.get(), 6);
303741143878b23d22cd9cb7b9cba8055179115ce17msarett        bytesPerColor = 3;
304741143878b23d22cd9cb7b9cba8055179115ce17msarett    } else {
305741143878b23d22cd9cb7b9cba8055179115ce17msarett        // There are no valid bmp headers
306230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: second bitmap header size is invalid.\n");
30779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return false;
308741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
309741143878b23d22cd9cb7b9cba8055179115ce17msarett
310741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Check for valid dimensions from header
311741143878b23d22cd9cb7b9cba8055179115ce17msarett    RowOrder rowOrder = kBottomUp_RowOrder;
312741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (height < 0) {
313741143878b23d22cd9cb7b9cba8055179115ce17msarett        height = -height;
314741143878b23d22cd9cb7b9cba8055179115ce17msarett        rowOrder = kTopDown_RowOrder;
315741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
3169bde918754bc292469d801f156f3b626eb3db780msarett    // The height field for bmp in ico is double the actual height because they
3179bde918754bc292469d801f156f3b626eb3db780msarett    // contain an XOR mask followed by an AND mask
3189bde918754bc292469d801f156f3b626eb3db780msarett    if (isIco) {
3199bde918754bc292469d801f156f3b626eb3db780msarett        height /= 2;
3209bde918754bc292469d801f156f3b626eb3db780msarett    }
3214b17fa353e777de309ca8b0706f1d3e326b59822msarett    if (width <= 0 || height <= 0) {
3224b17fa353e777de309ca8b0706f1d3e326b59822msarett        // TODO: Decide if we want to disable really large bmps as well.
3234b17fa353e777de309ca8b0706f1d3e326b59822msarett        // https://code.google.com/p/skia/issues/detail?id=3617
324230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: invalid bitmap dimensions.\n");
32579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return false;
326741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
327741143878b23d22cd9cb7b9cba8055179115ce17msarett
328741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Create mask struct
329741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkMasks::InputMasks inputMasks;
330eed039b5ffbdff958053ac80b09451ad6caa1787msarett    memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
331741143878b23d22cd9cb7b9cba8055179115ce17msarett
332741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Determine the input compression format and set bit masks if necessary
333741143878b23d22cd9cb7b9cba8055179115ce17msarett    uint32_t maskBytes = 0;
334741143878b23d22cd9cb7b9cba8055179115ce17msarett    BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
335741143878b23d22cd9cb7b9cba8055179115ce17msarett    switch (compression) {
336741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kNone_BitmapCompressionMethod:
337741143878b23d22cd9cb7b9cba8055179115ce17msarett            inputFormat = kStandard_BitmapInputFormat;
338741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
339741143878b23d22cd9cb7b9cba8055179115ce17msarett        case k8BitRLE_BitmapCompressionMethod:
340741143878b23d22cd9cb7b9cba8055179115ce17msarett            if (bitsPerPixel != 8) {
341230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
342741143878b23d22cd9cb7b9cba8055179115ce17msarett                bitsPerPixel = 8;
343741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
344741143878b23d22cd9cb7b9cba8055179115ce17msarett            inputFormat = kRLE_BitmapInputFormat;
345741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
346741143878b23d22cd9cb7b9cba8055179115ce17msarett        case k4BitRLE_BitmapCompressionMethod:
347741143878b23d22cd9cb7b9cba8055179115ce17msarett            if (bitsPerPixel != 4) {
348230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
349741143878b23d22cd9cb7b9cba8055179115ce17msarett                bitsPerPixel = 4;
350741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
351741143878b23d22cd9cb7b9cba8055179115ce17msarett            inputFormat = kRLE_BitmapInputFormat;
352741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
353741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kAlphaBitMasks_BitmapCompressionMethod:
354741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kBitMasks_BitmapCompressionMethod:
355741143878b23d22cd9cb7b9cba8055179115ce17msarett            // Load the masks
356741143878b23d22cd9cb7b9cba8055179115ce17msarett            inputFormat = kBitMask_BitmapInputFormat;
357741143878b23d22cd9cb7b9cba8055179115ce17msarett            switch (headerType) {
358741143878b23d22cd9cb7b9cba8055179115ce17msarett                case kInfoV1_BitmapHeaderType: {
359741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // The V1 header stores the bit masks after the header
360741143878b23d22cd9cb7b9cba8055179115ce17msarett                    SkAutoTDeleteArray<uint8_t> mBuffer(
361741143878b23d22cd9cb7b9cba8055179115ce17msarett                            SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
362741143878b23d22cd9cb7b9cba8055179115ce17msarett                    if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
363741143878b23d22cd9cb7b9cba8055179115ce17msarett                            kBmpMaskBytes) {
364230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                        SkCodecPrintf("Error: unable to read bit inputMasks.\n");
36579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                        return false;
366741143878b23d22cd9cb7b9cba8055179115ce17msarett                    }
367741143878b23d22cd9cb7b9cba8055179115ce17msarett                    maskBytes = kBmpMaskBytes;
368741143878b23d22cd9cb7b9cba8055179115ce17msarett                    inputMasks.red = get_int(mBuffer.get(), 0);
369741143878b23d22cd9cb7b9cba8055179115ce17msarett                    inputMasks.green = get_int(mBuffer.get(), 4);
370741143878b23d22cd9cb7b9cba8055179115ce17msarett                    inputMasks.blue = get_int(mBuffer.get(), 8);
371741143878b23d22cd9cb7b9cba8055179115ce17msarett                    break;
372741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
373741143878b23d22cd9cb7b9cba8055179115ce17msarett                case kInfoV2_BitmapHeaderType:
374741143878b23d22cd9cb7b9cba8055179115ce17msarett                case kInfoV3_BitmapHeaderType:
375741143878b23d22cd9cb7b9cba8055179115ce17msarett                case kInfoV4_BitmapHeaderType:
376741143878b23d22cd9cb7b9cba8055179115ce17msarett                case kInfoV5_BitmapHeaderType:
377741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Header types are matched based on size.  If the header
378741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // is V2+, we are guaranteed to be able to read at least
379741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // this size.
380741143878b23d22cd9cb7b9cba8055179115ce17msarett                    SkASSERT(infoBytesRemaining >= 48);
381741143878b23d22cd9cb7b9cba8055179115ce17msarett                    inputMasks.red = get_int(iBuffer.get(), 36);
382741143878b23d22cd9cb7b9cba8055179115ce17msarett                    inputMasks.green = get_int(iBuffer.get(), 40);
383741143878b23d22cd9cb7b9cba8055179115ce17msarett                    inputMasks.blue = get_int(iBuffer.get(), 44);
384741143878b23d22cd9cb7b9cba8055179115ce17msarett                    break;
385741143878b23d22cd9cb7b9cba8055179115ce17msarett                case kOS2VX_BitmapHeaderType:
386741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // TODO: Decide if we intend to support this.
387741143878b23d22cd9cb7b9cba8055179115ce17msarett                    //       It is unsupported in the previous version and
388741143878b23d22cd9cb7b9cba8055179115ce17msarett                    //       in chromium.  I have not come across a test case
389741143878b23d22cd9cb7b9cba8055179115ce17msarett                    //       that uses this format.
390230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                    SkCodecPrintf("Error: huffman format unsupported.\n");
39179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                    return false;
392741143878b23d22cd9cb7b9cba8055179115ce17msarett                default:
393230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                   SkCodecPrintf("Error: invalid bmp bit masks header.\n");
39479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                   return false;
395741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
396741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
397741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kJpeg_BitmapCompressionMethod:
398741143878b23d22cd9cb7b9cba8055179115ce17msarett            if (24 == bitsPerPixel) {
399741143878b23d22cd9cb7b9cba8055179115ce17msarett                inputFormat = kRLE_BitmapInputFormat;
400741143878b23d22cd9cb7b9cba8055179115ce17msarett                break;
401741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
402741143878b23d22cd9cb7b9cba8055179115ce17msarett            // Fall through
403741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kPng_BitmapCompressionMethod:
404741143878b23d22cd9cb7b9cba8055179115ce17msarett            // TODO: Decide if we intend to support this.
405741143878b23d22cd9cb7b9cba8055179115ce17msarett            //       It is unsupported in the previous version and
406741143878b23d22cd9cb7b9cba8055179115ce17msarett            //       in chromium.  I think it is used mostly for printers.
407230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: compression format not supported.\n");
40879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
409741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kCMYK_BitmapCompressionMethod:
410741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kCMYK8BitRLE_BitmapCompressionMethod:
411741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kCMYK4BitRLE_BitmapCompressionMethod:
412741143878b23d22cd9cb7b9cba8055179115ce17msarett            // TODO: Same as above.
413230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
41479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
415741143878b23d22cd9cb7b9cba8055179115ce17msarett        default:
416230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
41779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
418741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
419741143878b23d22cd9cb7b9cba8055179115ce17msarett
420741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Most versions of bmps should be rendered as opaque.  Either they do
421741143878b23d22cd9cb7b9cba8055179115ce17msarett    // not have an alpha channel, or they expect the alpha channel to be
4229bde918754bc292469d801f156f3b626eb3db780msarett    // ignored.  V3+ bmp files introduce an alpha mask and allow the creator
423741143878b23d22cd9cb7b9cba8055179115ce17msarett    // of the image to use the alpha channels.  However, many of these images
4249bde918754bc292469d801f156f3b626eb3db780msarett    // leave the alpha channel blank and expect to be rendered as opaque.  This
4259bde918754bc292469d801f156f3b626eb3db780msarett    // is the case for almost all V3 images, so we render these as opaque.  For
4269bde918754bc292469d801f156f3b626eb3db780msarett    // V4+, we will use the alpha channel, and fix the image later if it turns
4279bde918754bc292469d801f156f3b626eb3db780msarett    // out to be fully transparent.
4289bde918754bc292469d801f156f3b626eb3db780msarett    // As an exception, V3 bmp-in-ico may use an alpha mask.
429741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkAlphaType alphaType = kOpaque_SkAlphaType;
4309bde918754bc292469d801f156f3b626eb3db780msarett    if ((kInfoV3_BitmapHeaderType == headerType && isIco) ||
4319bde918754bc292469d801f156f3b626eb3db780msarett            kInfoV4_BitmapHeaderType == headerType ||
432741143878b23d22cd9cb7b9cba8055179115ce17msarett            kInfoV5_BitmapHeaderType == headerType) {
433741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Header types are matched based on size.  If the header is
4349bde918754bc292469d801f156f3b626eb3db780msarett        // V3+, we are guaranteed to be able to read at least this size.
435741143878b23d22cd9cb7b9cba8055179115ce17msarett        SkASSERT(infoBytesRemaining > 52);
436741143878b23d22cd9cb7b9cba8055179115ce17msarett        inputMasks.alpha = get_int(iBuffer.get(), 48);
437741143878b23d22cd9cb7b9cba8055179115ce17msarett        if (inputMasks.alpha != 0) {
438741143878b23d22cd9cb7b9cba8055179115ce17msarett            alphaType = kUnpremul_SkAlphaType;
439741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
440741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
441741143878b23d22cd9cb7b9cba8055179115ce17msarett    iBuffer.free();
442741143878b23d22cd9cb7b9cba8055179115ce17msarett
443438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Additionally, 32 bit bmp-in-icos use the alpha channel.
444438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // And, RLE inputs may skip pixels, leaving them as transparent.  This
445438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // is uncommon, but we cannot be certain that an RLE bmp will be opaque.
446438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat)) {
4479bde918754bc292469d801f156f3b626eb3db780msarett        alphaType = kUnpremul_SkAlphaType;
4489bde918754bc292469d801f156f3b626eb3db780msarett    }
4499bde918754bc292469d801f156f3b626eb3db780msarett
450438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Check for valid bits per pixel.
451438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // At the same time, use this information to choose a suggested color type
452438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // and to set default masks.
453438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkColorType colorType = kN32_SkColorType;
454741143878b23d22cd9cb7b9cba8055179115ce17msarett    switch (bitsPerPixel) {
455741143878b23d22cd9cb7b9cba8055179115ce17msarett        // In addition to more standard pixel compression formats, bmp supports
456741143878b23d22cd9cb7b9cba8055179115ce17msarett        // the use of bit masks to determine pixel components.  The standard
457741143878b23d22cd9cb7b9cba8055179115ce17msarett        // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
458741143878b23d22cd9cb7b9cba8055179115ce17msarett        // which does not map well to any Skia color formats.  For this reason,
459741143878b23d22cd9cb7b9cba8055179115ce17msarett        // we will always enable mask mode with 16 bits per pixel.
460741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 16:
461741143878b23d22cd9cb7b9cba8055179115ce17msarett            if (kBitMask_BitmapInputFormat != inputFormat) {
462741143878b23d22cd9cb7b9cba8055179115ce17msarett                inputMasks.red = 0x7C00;
463741143878b23d22cd9cb7b9cba8055179115ce17msarett                inputMasks.green = 0x03E0;
464741143878b23d22cd9cb7b9cba8055179115ce17msarett                inputMasks.blue = 0x001F;
465741143878b23d22cd9cb7b9cba8055179115ce17msarett                inputFormat = kBitMask_BitmapInputFormat;
466741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
467741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
468438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // We want to decode to kIndex_8 for input formats that are already
469438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // designed in index format.
470741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 1:
471741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 2:
472741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 4:
473741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 8:
474438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // However, we cannot in RLE format since we may need to leave some
475438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // pixels as transparent.  Similarly, we also cannot for ICO images
476438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // since we may need to apply a transparent mask.
477438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            if (kRLE_BitmapInputFormat != inputFormat && !isIco) {
478438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                colorType = kIndex_8_SkColorType;
479438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            }
480741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 24:
481741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 32:
482741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
483741143878b23d22cd9cb7b9cba8055179115ce17msarett        default:
484230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
48579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return false;
486741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
487741143878b23d22cd9cb7b9cba8055179115ce17msarett
488741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Check that input bit masks are valid and create the masks object
489741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkAutoTDelete<SkMasks>
490741143878b23d22cd9cb7b9cba8055179115ce17msarett            masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
491741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (NULL == masks) {
492230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: invalid input masks.\n");
49379e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return false;
494741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
495741143878b23d22cd9cb7b9cba8055179115ce17msarett
496eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Check for a valid number of total bytes when in RLE mode
497eed039b5ffbdff958053ac80b09451ad6caa1787msarett    if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) {
498230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: RLE requires valid input size.\n");
49979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return false;
500741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
501eed039b5ffbdff958053ac80b09451ad6caa1787msarett    const size_t RLEBytes = totalBytes - offset;
502741143878b23d22cd9cb7b9cba8055179115ce17msarett
503eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Calculate the number of bytes read so far
504eed039b5ffbdff958053ac80b09451ad6caa1787msarett    const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
5059bde918754bc292469d801f156f3b626eb3db780msarett    if (!isIco && offset < bytesRead) {
506230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: pixel data offset less than header size.\n");
50779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return false;
508741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
509741143878b23d22cd9cb7b9cba8055179115ce17msarett
51079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    if (codecOut) {
51179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        // Return the codec
512438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // We will use ImageInfo to store width, height, suggested color type, and
513438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // suggested alpha type.
51479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
515438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                colorType, alphaType);
51679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
51779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                                            inputFormat, masks.detach(),
51879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                                            numColors, bytesPerColor,
51979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                                            offset - bytesRead, rowOrder,
52079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo                                            RLEBytes, isIco));
52179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    }
52279e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    return true;
52379e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo}
52479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo
52579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo/*
52679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo *
52779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * Creates a bmp decoder
52879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * Reads enough of the stream to determine the image format
52979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo *
53079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo */
53179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggoSkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) {
5320a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo    SkAutoTDelete<SkStream> streamDeleter(stream);
53379e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    SkCodec* codec = NULL;
53479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    if (ReadHeader(stream, isIco, &codec)) {
5350a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo        // codec has taken ownership of stream, so we do not need to
5360a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo        // delete it.
5370a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo        SkASSERT(codec);
5380a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo        streamDeleter.detach();
53979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        return codec;
54079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    }
54179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo    return NULL;
542741143878b23d22cd9cb7b9cba8055179115ce17msarett}
543741143878b23d22cd9cb7b9cba8055179115ce17msarett
544741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
545741143878b23d22cd9cb7b9cba8055179115ce17msarett *
546741143878b23d22cd9cb7b9cba8055179115ce17msarett * Creates an instance of the decoder
547741143878b23d22cd9cb7b9cba8055179115ce17msarett * Called only by NewFromStream
548741143878b23d22cd9cb7b9cba8055179115ce17msarett *
549741143878b23d22cd9cb7b9cba8055179115ce17msarett */
550741143878b23d22cd9cb7b9cba8055179115ce17msarettSkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
551741143878b23d22cd9cb7b9cba8055179115ce17msarett                       uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
552eed039b5ffbdff958053ac80b09451ad6caa1787msarett                       SkMasks* masks, uint32_t numColors,
553eed039b5ffbdff958053ac80b09451ad6caa1787msarett                       uint32_t bytesPerColor, uint32_t offset,
5549bde918754bc292469d801f156f3b626eb3db780msarett                       RowOrder rowOrder, size_t RLEBytes, bool isIco)
555741143878b23d22cd9cb7b9cba8055179115ce17msarett    : INHERITED(info, stream)
556741143878b23d22cd9cb7b9cba8055179115ce17msarett    , fBitsPerPixel(bitsPerPixel)
557741143878b23d22cd9cb7b9cba8055179115ce17msarett    , fInputFormat(inputFormat)
558741143878b23d22cd9cb7b9cba8055179115ce17msarett    , fMasks(masks)
559eed039b5ffbdff958053ac80b09451ad6caa1787msarett    , fColorTable(NULL)
560eed039b5ffbdff958053ac80b09451ad6caa1787msarett    , fNumColors(numColors)
561eed039b5ffbdff958053ac80b09451ad6caa1787msarett    , fBytesPerColor(bytesPerColor)
562eed039b5ffbdff958053ac80b09451ad6caa1787msarett    , fOffset(offset)
563741143878b23d22cd9cb7b9cba8055179115ce17msarett    , fRowOrder(rowOrder)
564eed039b5ffbdff958053ac80b09451ad6caa1787msarett    , fRLEBytes(RLEBytes)
5659bde918754bc292469d801f156f3b626eb3db780msarett    , fIsIco(isIco)
5669bde918754bc292469d801f156f3b626eb3db780msarett
567741143878b23d22cd9cb7b9cba8055179115ce17msarett{}
568741143878b23d22cd9cb7b9cba8055179115ce17msarett
569741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
570741143878b23d22cd9cb7b9cba8055179115ce17msarett *
571741143878b23d22cd9cb7b9cba8055179115ce17msarett * Initiates the bitmap decode
572741143878b23d22cd9cb7b9cba8055179115ce17msarett *
573741143878b23d22cd9cb7b9cba8055179115ce17msarett */
574741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
575741143878b23d22cd9cb7b9cba8055179115ce17msarett                                        void* dst, size_t dstRowBytes,
576438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                        const Options& opts,
577438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                        SkPMColor* inputColorPtr,
578438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                        int* inputColorCount) {
579eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Check for proper input and output formats
580a096d7a6d03662073f4cd46f7db5fe2cf5495c36halcanary    SkCodec::RewindState rewindState = this->rewindIfNeeded();
581a096d7a6d03662073f4cd46f7db5fe2cf5495c36halcanary    if (rewindState == kCouldNotRewind_RewindState) {
582741143878b23d22cd9cb7b9cba8055179115ce17msarett        return kCouldNotRewind;
583a096d7a6d03662073f4cd46f7db5fe2cf5495c36halcanary    } else if (rewindState == kRewound_RewindState) {
58479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        if (!ReadHeader(this->stream(), fIsIco, NULL)) {
58579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo            return kCouldNotRewind;
58679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo        }
587741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
5889bde918754bc292469d801f156f3b626eb3db780msarett    if (dstInfo.dimensions() != this->getInfo().dimensions()) {
589230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: scaling not supported.\n");
590741143878b23d22cd9cb7b9cba8055179115ce17msarett        return kInvalidScale;
591741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
5929bde918754bc292469d801f156f3b626eb3db780msarett    if (!conversion_possible(dstInfo, this->getInfo())) {
593230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: cannot convert input type to output type.\n");
594741143878b23d22cd9cb7b9cba8055179115ce17msarett        return kInvalidConversion;
595741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
596741143878b23d22cd9cb7b9cba8055179115ce17msarett
597eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Create the color table if necessary and prepare the stream for decode
598438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Note that if it is non-NULL, inputColorCount will be modified
599438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (!createColorTable(dstInfo.alphaType(), inputColorCount)) {
600230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: could not create color table.\n");
601eed039b5ffbdff958053ac80b09451ad6caa1787msarett        return kInvalidInput;
602eed039b5ffbdff958053ac80b09451ad6caa1787msarett    }
603eed039b5ffbdff958053ac80b09451ad6caa1787msarett
604438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Copy the color table to the client if necessary
6059e43cabaa1ff26167e990f0bcb9a5c20d662d52cmsarett    copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount);
606438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
607eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Perform the decode
608741143878b23d22cd9cb7b9cba8055179115ce17msarett    switch (fInputFormat) {
609741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kBitMask_BitmapInputFormat:
6103c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            return decodeMask(dstInfo, dst, dstRowBytes, opts);
611741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kRLE_BitmapInputFormat:
612438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            return decodeRLE(dstInfo, dst, dstRowBytes, opts);
613741143878b23d22cd9cb7b9cba8055179115ce17msarett        case kStandard_BitmapInputFormat:
6143c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            return decode(dstInfo, dst, dstRowBytes, opts);
615741143878b23d22cd9cb7b9cba8055179115ce17msarett        default:
616741143878b23d22cd9cb7b9cba8055179115ce17msarett            SkASSERT(false);
617741143878b23d22cd9cb7b9cba8055179115ce17msarett            return kInvalidInput;
618741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
619741143878b23d22cd9cb7b9cba8055179115ce17msarett}
620741143878b23d22cd9cb7b9cba8055179115ce17msarett
621741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
622741143878b23d22cd9cb7b9cba8055179115ce17msarett *
623eed039b5ffbdff958053ac80b09451ad6caa1787msarett * Process the color table for the bmp input
624eed039b5ffbdff958053ac80b09451ad6caa1787msarett *
625eed039b5ffbdff958053ac80b09451ad6caa1787msarett */
626438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett bool SkBmpCodec::createColorTable(SkAlphaType alphaType, int* numColors) {
627eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Allocate memory for color table
628eed039b5ffbdff958053ac80b09451ad6caa1787msarett    uint32_t colorBytes = 0;
629eed039b5ffbdff958053ac80b09451ad6caa1787msarett    uint32_t maxColors = 0;
630eed039b5ffbdff958053ac80b09451ad6caa1787msarett    SkPMColor colorTable[256];
631eed039b5ffbdff958053ac80b09451ad6caa1787msarett    if (fBitsPerPixel <= 8) {
632eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // Zero is a default for maxColors
633eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // Also set fNumColors to maxColors when it is too large
634eed039b5ffbdff958053ac80b09451ad6caa1787msarett        maxColors = 1 << fBitsPerPixel;
635eed039b5ffbdff958053ac80b09451ad6caa1787msarett        if (fNumColors == 0 || fNumColors >= maxColors) {
636eed039b5ffbdff958053ac80b09451ad6caa1787msarett            fNumColors = maxColors;
637eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
638eed039b5ffbdff958053ac80b09451ad6caa1787msarett
639438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // Inform the caller of the number of colors
640438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        if (NULL != numColors) {
641438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // We set the number of colors to maxColors in order to ensure
642438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // safe memory accesses.  Otherwise, an invalid pixel could
643438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // access memory outside of our color table array.
644438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            *numColors = maxColors;
645438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        }
646438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
647eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // Read the color table from the stream
648eed039b5ffbdff958053ac80b09451ad6caa1787msarett        colorBytes = fNumColors * fBytesPerColor;
649eed039b5ffbdff958053ac80b09451ad6caa1787msarett        SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
650eed039b5ffbdff958053ac80b09451ad6caa1787msarett        if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
651230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: unable to read color table.\n");
652eed039b5ffbdff958053ac80b09451ad6caa1787msarett            return false;
653eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
654eed039b5ffbdff958053ac80b09451ad6caa1787msarett
655eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // Choose the proper packing function
656eed039b5ffbdff958053ac80b09451ad6caa1787msarett        SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t);
657eed039b5ffbdff958053ac80b09451ad6caa1787msarett        switch (alphaType) {
658eed039b5ffbdff958053ac80b09451ad6caa1787msarett            case kOpaque_SkAlphaType:
659eed039b5ffbdff958053ac80b09451ad6caa1787msarett            case kUnpremul_SkAlphaType:
660eed039b5ffbdff958053ac80b09451ad6caa1787msarett                packARGB = &SkPackARGB32NoCheck;
661eed039b5ffbdff958053ac80b09451ad6caa1787msarett                break;
662eed039b5ffbdff958053ac80b09451ad6caa1787msarett            case kPremul_SkAlphaType:
663eed039b5ffbdff958053ac80b09451ad6caa1787msarett                packARGB = &SkPreMultiplyARGB;
664eed039b5ffbdff958053ac80b09451ad6caa1787msarett                break;
665eed039b5ffbdff958053ac80b09451ad6caa1787msarett            default:
666eed039b5ffbdff958053ac80b09451ad6caa1787msarett                // This should not be reached because conversion possible
667eed039b5ffbdff958053ac80b09451ad6caa1787msarett                // should fail if the alpha type is not one of the above
668eed039b5ffbdff958053ac80b09451ad6caa1787msarett                // values.
669eed039b5ffbdff958053ac80b09451ad6caa1787msarett                SkASSERT(false);
670eed039b5ffbdff958053ac80b09451ad6caa1787msarett                packARGB = NULL;
671eed039b5ffbdff958053ac80b09451ad6caa1787msarett                break;
672eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
673eed039b5ffbdff958053ac80b09451ad6caa1787msarett
674eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // Fill in the color table
675eed039b5ffbdff958053ac80b09451ad6caa1787msarett        uint32_t i = 0;
676eed039b5ffbdff958053ac80b09451ad6caa1787msarett        for (; i < fNumColors; i++) {
677eed039b5ffbdff958053ac80b09451ad6caa1787msarett            uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
678eed039b5ffbdff958053ac80b09451ad6caa1787msarett            uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
679eed039b5ffbdff958053ac80b09451ad6caa1787msarett            uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
680438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            uint8_t alpha;
681438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            if (kOpaque_SkAlphaType == alphaType || kRLE_BitmapInputFormat == fInputFormat) {
682438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                alpha = 0xFF;
683438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            } else {
684438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                alpha = (fMasks->getAlphaMask() >> 24) &
685438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                        get_byte(cBuffer.get(), i*fBytesPerColor + 3);
686438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            }
687eed039b5ffbdff958053ac80b09451ad6caa1787msarett            colorTable[i] = packARGB(alpha, red, green, blue);
688eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
689eed039b5ffbdff958053ac80b09451ad6caa1787msarett
690eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // To avoid segmentation faults on bad pixel data, fill the end of the
691eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // color table with black.  This is the same the behavior as the
692eed039b5ffbdff958053ac80b09451ad6caa1787msarett        // chromium decoder.
693eed039b5ffbdff958053ac80b09451ad6caa1787msarett        for (; i < maxColors; i++) {
694eed039b5ffbdff958053ac80b09451ad6caa1787msarett            colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
695eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
6963c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett
6973c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett        // Set the color table
6983c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett        fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
699eed039b5ffbdff958053ac80b09451ad6caa1787msarett    }
700eed039b5ffbdff958053ac80b09451ad6caa1787msarett
7019bde918754bc292469d801f156f3b626eb3db780msarett    // Bmp-in-Ico files do not use an offset to indicate where the pixel data
7029bde918754bc292469d801f156f3b626eb3db780msarett    // begins.  Pixel data always begins immediately after the color table.
7039bde918754bc292469d801f156f3b626eb3db780msarett    if (!fIsIco) {
7049bde918754bc292469d801f156f3b626eb3db780msarett        // Check that we have not read past the pixel array offset
7059bde918754bc292469d801f156f3b626eb3db780msarett        if(fOffset < colorBytes) {
7069bde918754bc292469d801f156f3b626eb3db780msarett            // This may occur on OS 2.1 and other old versions where the color
7079bde918754bc292469d801f156f3b626eb3db780msarett            // table defaults to max size, and the bmp tries to use a smaller
7089bde918754bc292469d801f156f3b626eb3db780msarett            // color table.  This is invalid, and our decision is to indicate
7099bde918754bc292469d801f156f3b626eb3db780msarett            // an error, rather than try to guess the intended size of the
7109bde918754bc292469d801f156f3b626eb3db780msarett            // color table.
711230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: pixel data offset less than color table size.\n");
7129bde918754bc292469d801f156f3b626eb3db780msarett            return false;
7139bde918754bc292469d801f156f3b626eb3db780msarett        }
714eed039b5ffbdff958053ac80b09451ad6caa1787msarett
7159bde918754bc292469d801f156f3b626eb3db780msarett        // After reading the color table, skip to the start of the pixel array
7169bde918754bc292469d801f156f3b626eb3db780msarett        if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
717230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Error: unable to skip to image data.\n");
7189bde918754bc292469d801f156f3b626eb3db780msarett            return false;
7199bde918754bc292469d801f156f3b626eb3db780msarett        }
720eed039b5ffbdff958053ac80b09451ad6caa1787msarett    }
721eed039b5ffbdff958053ac80b09451ad6caa1787msarett
7223c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett    // Return true on success
723eed039b5ffbdff958053ac80b09451ad6caa1787msarett    return true;
724eed039b5ffbdff958053ac80b09451ad6caa1787msarett}
725eed039b5ffbdff958053ac80b09451ad6caa1787msarett
726eed039b5ffbdff958053ac80b09451ad6caa1787msarett/*
727eed039b5ffbdff958053ac80b09451ad6caa1787msarett *
7283c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett * Get the destination row to start filling from
7293c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett * Used to fill the remainder of the image on incomplete input
7303c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett *
7313c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett */
7323c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarettstatic inline void* get_dst_start_row(void* dst, size_t dstRowBytes, int32_t y,
7333c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            SkBmpCodec::RowOrder rowOrder) {
7343c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett    return (SkBmpCodec::kTopDown_RowOrder == rowOrder) ?
7353c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            SkTAddOffset<void*>(dst, y * dstRowBytes) : dst;
7363c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett}
7373c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett
7383c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett/*
7393c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett *
740741143878b23d22cd9cb7b9cba8055179115ce17msarett * Performs the bitmap decoding for bit masks input format
741741143878b23d22cd9cb7b9cba8055179115ce17msarett *
742741143878b23d22cd9cb7b9cba8055179115ce17msarett */
743741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
7443c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett                                       void* dst, size_t dstRowBytes,
7453c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett                                       const Options& opts) {
746741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Set constant values
747741143878b23d22cd9cb7b9cba8055179115ce17msarett    const int width = dstInfo.width();
748741143878b23d22cd9cb7b9cba8055179115ce17msarett    const int height = dstInfo.height();
749741143878b23d22cd9cb7b9cba8055179115ce17msarett    const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
750741143878b23d22cd9cb7b9cba8055179115ce17msarett
751eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Allocate a buffer large enough to hold the full image
752eed039b5ffbdff958053ac80b09451ad6caa1787msarett    SkAutoTDeleteArray<uint8_t>
753eed039b5ffbdff958053ac80b09451ad6caa1787msarett        srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes));
754eed039b5ffbdff958053ac80b09451ad6caa1787msarett    uint8_t* srcRow = srcBuffer.get();
755741143878b23d22cd9cb7b9cba8055179115ce17msarett
756741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Create the swizzler
757eed039b5ffbdff958053ac80b09451ad6caa1787msarett    SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
758eed039b5ffbdff958053ac80b09451ad6caa1787msarett            SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes,
759eed039b5ffbdff958053ac80b09451ad6caa1787msarett            fMasks, fBitsPerPixel));
760741143878b23d22cd9cb7b9cba8055179115ce17msarett
761741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Iterate over rows of the image
762741143878b23d22cd9cb7b9cba8055179115ce17msarett    bool transparent = true;
763741143878b23d22cd9cb7b9cba8055179115ce17msarett    for (int y = 0; y < height; y++) {
764741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Read a row of the input
765eed039b5ffbdff958053ac80b09451ad6caa1787msarett        if (stream()->read(srcRow, rowBytes) != rowBytes) {
766230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Warning: incomplete input stream.\n");
7673c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            // Fill the destination image on failure
768e16b04aa6041efb6507546547737e9603fa1606emsarett            SkPMColor fillColor = dstInfo.alphaType() == kOpaque_SkAlphaType ?
769e16b04aa6041efb6507546547737e9603fa1606emsarett                    SK_ColorBLACK : SK_ColorTRANSPARENT;
770e16b04aa6041efb6507546547737e9603fa1606emsarett            if (kNo_ZeroInitialized == opts.fZeroInitialized || 0 != fillColor) {
7713c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett                void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrder);
772e16b04aa6041efb6507546547737e9603fa1606emsarett                SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y, fillColor,
773e16b04aa6041efb6507546547737e9603fa1606emsarett                        NULL);
7743c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            }
775741143878b23d22cd9cb7b9cba8055179115ce17msarett            return kIncompleteInput;
776741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
777741143878b23d22cd9cb7b9cba8055179115ce17msarett
778741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Decode the row in destination format
779eed039b5ffbdff958053ac80b09451ad6caa1787msarett        int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
780eed039b5ffbdff958053ac80b09451ad6caa1787msarett        SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row);
781741143878b23d22cd9cb7b9cba8055179115ce17msarett        transparent &= SkSwizzler::IsTransparent(r);
782741143878b23d22cd9cb7b9cba8055179115ce17msarett
783741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Move to the next row
784eed039b5ffbdff958053ac80b09451ad6caa1787msarett        srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
785741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
786741143878b23d22cd9cb7b9cba8055179115ce17msarett
787741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Some fully transparent bmp images are intended to be opaque.  Here, we
788741143878b23d22cd9cb7b9cba8055179115ce17msarett    // correct for this possibility.
789741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (transparent) {
790eed039b5ffbdff958053ac80b09451ad6caa1787msarett        const SkImageInfo& opaqueInfo =
791eed039b5ffbdff958053ac80b09451ad6caa1787msarett                dstInfo.makeAlphaType(kOpaque_SkAlphaType);
792eed039b5ffbdff958053ac80b09451ad6caa1787msarett        SkAutoTDelete<SkMaskSwizzler> opaqueSwizzler(
793eed039b5ffbdff958053ac80b09451ad6caa1787msarett                SkMaskSwizzler::CreateMaskSwizzler(opaqueInfo, dst, dstRowBytes,
794eed039b5ffbdff958053ac80b09451ad6caa1787msarett                                                   fMasks, fBitsPerPixel));
795eed039b5ffbdff958053ac80b09451ad6caa1787msarett        srcRow = srcBuffer.get();
796741143878b23d22cd9cb7b9cba8055179115ce17msarett        for (int y = 0; y < height; y++) {
797eed039b5ffbdff958053ac80b09451ad6caa1787msarett            // Decode the row in opaque format
798eed039b5ffbdff958053ac80b09451ad6caa1787msarett            int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
799eed039b5ffbdff958053ac80b09451ad6caa1787msarett            opaqueSwizzler->next(srcRow, row);
800eed039b5ffbdff958053ac80b09451ad6caa1787msarett
801eed039b5ffbdff958053ac80b09451ad6caa1787msarett            // Move to the next row
802eed039b5ffbdff958053ac80b09451ad6caa1787msarett            srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
803741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
804741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
805741143878b23d22cd9cb7b9cba8055179115ce17msarett
806741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Finished decoding the entire image
807741143878b23d22cd9cb7b9cba8055179115ce17msarett    return kSuccess;
808741143878b23d22cd9cb7b9cba8055179115ce17msarett}
809741143878b23d22cd9cb7b9cba8055179115ce17msarett
810741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
811741143878b23d22cd9cb7b9cba8055179115ce17msarett *
812741143878b23d22cd9cb7b9cba8055179115ce17msarett * Set an RLE pixel using the color table
813741143878b23d22cd9cb7b9cba8055179115ce17msarett *
814741143878b23d22cd9cb7b9cba8055179115ce17msarett */
815438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarettvoid SkBmpCodec::setRLEPixel(void* dst, size_t dstRowBytes,
816eed039b5ffbdff958053ac80b09451ad6caa1787msarett                             const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
817eed039b5ffbdff958053ac80b09451ad6caa1787msarett                             uint8_t index) {
818eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Set the row
819eed039b5ffbdff958053ac80b09451ad6caa1787msarett    int height = dstInfo.height();
820eed039b5ffbdff958053ac80b09451ad6caa1787msarett    int row;
821741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (kBottomUp_RowOrder == fRowOrder) {
822eed039b5ffbdff958053ac80b09451ad6caa1787msarett        row = height - y - 1;
823eed039b5ffbdff958053ac80b09451ad6caa1787msarett    } else {
824eed039b5ffbdff958053ac80b09451ad6caa1787msarett        row = y;
825eed039b5ffbdff958053ac80b09451ad6caa1787msarett    }
826eed039b5ffbdff958053ac80b09451ad6caa1787msarett
827eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Set the pixel based on destination color type
828eed039b5ffbdff958053ac80b09451ad6caa1787msarett    switch (dstInfo.colorType()) {
829eed039b5ffbdff958053ac80b09451ad6caa1787msarett        case kN32_SkColorType: {
830438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
831eed039b5ffbdff958053ac80b09451ad6caa1787msarett                    row * (int) dstRowBytes);
832eed039b5ffbdff958053ac80b09451ad6caa1787msarett            dstRow[x] = fColorTable->operator[](index);
833eed039b5ffbdff958053ac80b09451ad6caa1787msarett            break;
834eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
835eed039b5ffbdff958053ac80b09451ad6caa1787msarett        default:
836eed039b5ffbdff958053ac80b09451ad6caa1787msarett            // This case should not be reached.  We should catch an invalid
837eed039b5ffbdff958053ac80b09451ad6caa1787msarett            // color type when we check that the conversion is possible.
838eed039b5ffbdff958053ac80b09451ad6caa1787msarett            SkASSERT(false);
839eed039b5ffbdff958053ac80b09451ad6caa1787msarett            break;
840eed039b5ffbdff958053ac80b09451ad6caa1787msarett    }
841eed039b5ffbdff958053ac80b09451ad6caa1787msarett}
842eed039b5ffbdff958053ac80b09451ad6caa1787msarett
843eed039b5ffbdff958053ac80b09451ad6caa1787msarett/*
844eed039b5ffbdff958053ac80b09451ad6caa1787msarett *
845eed039b5ffbdff958053ac80b09451ad6caa1787msarett * Set an RLE pixel from R, G, B values
846eed039b5ffbdff958053ac80b09451ad6caa1787msarett *
847eed039b5ffbdff958053ac80b09451ad6caa1787msarett */
848438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarettvoid SkBmpCodec::setRLE24Pixel(void* dst, size_t dstRowBytes,
849eed039b5ffbdff958053ac80b09451ad6caa1787msarett                               const SkImageInfo& dstInfo, uint32_t x,
850eed039b5ffbdff958053ac80b09451ad6caa1787msarett                               uint32_t y, uint8_t red, uint8_t green,
851eed039b5ffbdff958053ac80b09451ad6caa1787msarett                               uint8_t blue) {
852eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Set the row
853eed039b5ffbdff958053ac80b09451ad6caa1787msarett    int height = dstInfo.height();
854eed039b5ffbdff958053ac80b09451ad6caa1787msarett    int row;
855eed039b5ffbdff958053ac80b09451ad6caa1787msarett    if (kBottomUp_RowOrder == fRowOrder) {
856eed039b5ffbdff958053ac80b09451ad6caa1787msarett        row = height - y - 1;
857eed039b5ffbdff958053ac80b09451ad6caa1787msarett    } else {
858eed039b5ffbdff958053ac80b09451ad6caa1787msarett        row = y;
859eed039b5ffbdff958053ac80b09451ad6caa1787msarett    }
860eed039b5ffbdff958053ac80b09451ad6caa1787msarett
861eed039b5ffbdff958053ac80b09451ad6caa1787msarett    // Set the pixel based on destination color type
862eed039b5ffbdff958053ac80b09451ad6caa1787msarett    switch (dstInfo.colorType()) {
863eed039b5ffbdff958053ac80b09451ad6caa1787msarett        case kN32_SkColorType: {
864438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
865eed039b5ffbdff958053ac80b09451ad6caa1787msarett                    row * (int) dstRowBytes);
866eed039b5ffbdff958053ac80b09451ad6caa1787msarett            dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue);
867eed039b5ffbdff958053ac80b09451ad6caa1787msarett            break;
868eed039b5ffbdff958053ac80b09451ad6caa1787msarett        }
869eed039b5ffbdff958053ac80b09451ad6caa1787msarett        default:
870eed039b5ffbdff958053ac80b09451ad6caa1787msarett            // This case should not be reached.  We should catch an invalid
871eed039b5ffbdff958053ac80b09451ad6caa1787msarett            // color type when we check that the conversion is possible.
872eed039b5ffbdff958053ac80b09451ad6caa1787msarett            SkASSERT(false);
873eed039b5ffbdff958053ac80b09451ad6caa1787msarett            break;
874741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
875741143878b23d22cd9cb7b9cba8055179115ce17msarett}
876741143878b23d22cd9cb7b9cba8055179115ce17msarett
877741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
878741143878b23d22cd9cb7b9cba8055179115ce17msarett *
879741143878b23d22cd9cb7b9cba8055179115ce17msarett * Performs the bitmap decoding for RLE input format
880741143878b23d22cd9cb7b9cba8055179115ce17msarett * RLE decoding is performed all at once, rather than a one row at a time
881741143878b23d22cd9cb7b9cba8055179115ce17msarett *
882741143878b23d22cd9cb7b9cba8055179115ce17msarett */
883741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
884438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                      void* dst, size_t dstRowBytes,
885438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                      const Options& opts) {
886741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Set RLE flags
887741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint8_t RLE_ESCAPE = 0;
888741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint8_t RLE_EOL = 0;
889741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint8_t RLE_EOF = 1;
890741143878b23d22cd9cb7b9cba8055179115ce17msarett    static const uint8_t RLE_DELTA = 2;
891741143878b23d22cd9cb7b9cba8055179115ce17msarett
892741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Set constant values
893741143878b23d22cd9cb7b9cba8055179115ce17msarett    const int width = dstInfo.width();
894741143878b23d22cd9cb7b9cba8055179115ce17msarett    const int height = dstInfo.height();
895741143878b23d22cd9cb7b9cba8055179115ce17msarett
896741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Input buffer parameters
897741143878b23d22cd9cb7b9cba8055179115ce17msarett    uint32_t currByte = 0;
898eed039b5ffbdff958053ac80b09451ad6caa1787msarett    SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
899eed039b5ffbdff958053ac80b09451ad6caa1787msarett    size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
900eed039b5ffbdff958053ac80b09451ad6caa1787msarett    if (totalBytes < fRLEBytes) {
901230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Warning: incomplete RLE file.\n");
902741143878b23d22cd9cb7b9cba8055179115ce17msarett    } else if (totalBytes <= 0) {
903230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo        SkCodecPrintf("Error: could not read RLE image data.\n");
904741143878b23d22cd9cb7b9cba8055179115ce17msarett        return kInvalidInput;
905741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
906741143878b23d22cd9cb7b9cba8055179115ce17msarett
907741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Destination parameters
908741143878b23d22cd9cb7b9cba8055179115ce17msarett    int x = 0;
909741143878b23d22cd9cb7b9cba8055179115ce17msarett    int y = 0;
910438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
911438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Set the background as transparent.  Then, if the RLE code skips pixels,
912438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // the skipped pixels will be transparent.
913438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Because of the need for transparent pixels, kN32 is the only color
914438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // type that makes sense for the destination format.
915438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkASSERT(kN32_SkColorType == dstInfo.colorType());
916438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (kNo_ZeroInitialized == opts.fZeroInitialized) {
9173c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett        SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL);
918438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
919741143878b23d22cd9cb7b9cba8055179115ce17msarett
920741143878b23d22cd9cb7b9cba8055179115ce17msarett    while (true) {
921741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Every entry takes at least two bytes
922741143878b23d22cd9cb7b9cba8055179115ce17msarett        if ((int) totalBytes - currByte < 2) {
923230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Warning: incomplete RLE input.\n");
924741143878b23d22cd9cb7b9cba8055179115ce17msarett            return kIncompleteInput;
925741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
926741143878b23d22cd9cb7b9cba8055179115ce17msarett
927741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Read the next two bytes.  These bytes have different meanings
928741143878b23d22cd9cb7b9cba8055179115ce17msarett        // depending on their values.  In the first interpretation, the first
929741143878b23d22cd9cb7b9cba8055179115ce17msarett        // byte is an escape flag and the second byte indicates what special
930741143878b23d22cd9cb7b9cba8055179115ce17msarett        // task to perform.
931741143878b23d22cd9cb7b9cba8055179115ce17msarett        const uint8_t flag = buffer.get()[currByte++];
932741143878b23d22cd9cb7b9cba8055179115ce17msarett        const uint8_t task = buffer.get()[currByte++];
933741143878b23d22cd9cb7b9cba8055179115ce17msarett
934741143878b23d22cd9cb7b9cba8055179115ce17msarett        // If we have reached a row that is beyond the image size, and the RLE
935741143878b23d22cd9cb7b9cba8055179115ce17msarett        // code does not indicate end of file, abort and signal a warning.
936741143878b23d22cd9cb7b9cba8055179115ce17msarett        if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) {
937230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Warning: invalid RLE input.\n");
938741143878b23d22cd9cb7b9cba8055179115ce17msarett            return kIncompleteInput;
939741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
940741143878b23d22cd9cb7b9cba8055179115ce17msarett
941741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Perform decoding
942741143878b23d22cd9cb7b9cba8055179115ce17msarett        if (RLE_ESCAPE == flag) {
943741143878b23d22cd9cb7b9cba8055179115ce17msarett            switch (task) {
944741143878b23d22cd9cb7b9cba8055179115ce17msarett                case RLE_EOL:
945741143878b23d22cd9cb7b9cba8055179115ce17msarett                    x = 0;
946741143878b23d22cd9cb7b9cba8055179115ce17msarett                    y++;
947741143878b23d22cd9cb7b9cba8055179115ce17msarett                    break;
948741143878b23d22cd9cb7b9cba8055179115ce17msarett                case RLE_EOF:
949741143878b23d22cd9cb7b9cba8055179115ce17msarett                    return kSuccess;
950741143878b23d22cd9cb7b9cba8055179115ce17msarett                case RLE_DELTA: {
951741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Two bytes are needed to specify delta
952741143878b23d22cd9cb7b9cba8055179115ce17msarett                    if ((int) totalBytes - currByte < 2) {
953230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                        SkCodecPrintf("Warning: incomplete RLE input\n");
954741143878b23d22cd9cb7b9cba8055179115ce17msarett                        return kIncompleteInput;
955741143878b23d22cd9cb7b9cba8055179115ce17msarett                    }
956741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Modify x and y
957741143878b23d22cd9cb7b9cba8055179115ce17msarett                    const uint8_t dx = buffer.get()[currByte++];
958741143878b23d22cd9cb7b9cba8055179115ce17msarett                    const uint8_t dy = buffer.get()[currByte++];
959741143878b23d22cd9cb7b9cba8055179115ce17msarett                    x += dx;
960741143878b23d22cd9cb7b9cba8055179115ce17msarett                    y += dy;
961741143878b23d22cd9cb7b9cba8055179115ce17msarett                    if (x > width || y > height) {
962230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                        SkCodecPrintf("Warning: invalid RLE input.\n");
963741143878b23d22cd9cb7b9cba8055179115ce17msarett                        return kIncompleteInput;
964741143878b23d22cd9cb7b9cba8055179115ce17msarett                    }
965741143878b23d22cd9cb7b9cba8055179115ce17msarett                    break;
966741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
967741143878b23d22cd9cb7b9cba8055179115ce17msarett                default: {
968741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // If task does not match any of the above signals, it
969741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // indicates that we have a sequence of non-RLE pixels.
970741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Furthermore, the value of task is equal to the number
971741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // of pixels to interpret.
972741143878b23d22cd9cb7b9cba8055179115ce17msarett                    uint8_t numPixels = task;
973741143878b23d22cd9cb7b9cba8055179115ce17msarett                    const size_t rowBytes = compute_row_bytes(numPixels,
974741143878b23d22cd9cb7b9cba8055179115ce17msarett                            fBitsPerPixel);
975741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Abort if setting numPixels moves us off the edge of the
976741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // image.  Also abort if there are not enough bytes
977741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // remaining in the stream to set numPixels.
978741143878b23d22cd9cb7b9cba8055179115ce17msarett                    if (x + numPixels > width ||
979741143878b23d22cd9cb7b9cba8055179115ce17msarett                            (int) totalBytes - currByte < SkAlign2(rowBytes)) {
980230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                        SkCodecPrintf("Warning: invalid RLE input.\n");
981741143878b23d22cd9cb7b9cba8055179115ce17msarett                        return kIncompleteInput;
982741143878b23d22cd9cb7b9cba8055179115ce17msarett                    }
983741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Set numPixels number of pixels
984741143878b23d22cd9cb7b9cba8055179115ce17msarett                    while (numPixels > 0) {
985741143878b23d22cd9cb7b9cba8055179115ce17msarett                        switch(fBitsPerPixel) {
986741143878b23d22cd9cb7b9cba8055179115ce17msarett                            case 4: {
987741143878b23d22cd9cb7b9cba8055179115ce17msarett                                SkASSERT(currByte < totalBytes);
988741143878b23d22cd9cb7b9cba8055179115ce17msarett                                uint8_t val = buffer.get()[currByte++];
989438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                setRLEPixel(dst, dstRowBytes, dstInfo, x++,
990eed039b5ffbdff958053ac80b09451ad6caa1787msarett                                        y, val >> 4);
991741143878b23d22cd9cb7b9cba8055179115ce17msarett                                numPixels--;
992741143878b23d22cd9cb7b9cba8055179115ce17msarett                                if (numPixels != 0) {
993438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                    setRLEPixel(dst, dstRowBytes, dstInfo,
994741143878b23d22cd9cb7b9cba8055179115ce17msarett                                            x++, y, val & 0xF);
995741143878b23d22cd9cb7b9cba8055179115ce17msarett                                    numPixels--;
996741143878b23d22cd9cb7b9cba8055179115ce17msarett                                }
997741143878b23d22cd9cb7b9cba8055179115ce17msarett                                break;
998741143878b23d22cd9cb7b9cba8055179115ce17msarett                            }
999741143878b23d22cd9cb7b9cba8055179115ce17msarett                            case 8:
1000741143878b23d22cd9cb7b9cba8055179115ce17msarett                                SkASSERT(currByte < totalBytes);
1001438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                setRLEPixel(dst, dstRowBytes, dstInfo, x++,
1002eed039b5ffbdff958053ac80b09451ad6caa1787msarett                                        y, buffer.get()[currByte++]);
1003741143878b23d22cd9cb7b9cba8055179115ce17msarett                                numPixels--;
1004741143878b23d22cd9cb7b9cba8055179115ce17msarett                                break;
1005741143878b23d22cd9cb7b9cba8055179115ce17msarett                            case 24: {
1006741143878b23d22cd9cb7b9cba8055179115ce17msarett                                SkASSERT(currByte + 2 < totalBytes);
1007741143878b23d22cd9cb7b9cba8055179115ce17msarett                                uint8_t blue = buffer.get()[currByte++];
1008741143878b23d22cd9cb7b9cba8055179115ce17msarett                                uint8_t green = buffer.get()[currByte++];
1009741143878b23d22cd9cb7b9cba8055179115ce17msarett                                uint8_t red = buffer.get()[currByte++];
1010438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                                setRLE24Pixel(dst, dstRowBytes, dstInfo,
1011eed039b5ffbdff958053ac80b09451ad6caa1787msarett                                            x++, y, red, green, blue);
1012741143878b23d22cd9cb7b9cba8055179115ce17msarett                                numPixels--;
1013741143878b23d22cd9cb7b9cba8055179115ce17msarett                            }
1014741143878b23d22cd9cb7b9cba8055179115ce17msarett                            default:
1015741143878b23d22cd9cb7b9cba8055179115ce17msarett                                SkASSERT(false);
1016741143878b23d22cd9cb7b9cba8055179115ce17msarett                                return kInvalidInput;
1017741143878b23d22cd9cb7b9cba8055179115ce17msarett                        }
1018741143878b23d22cd9cb7b9cba8055179115ce17msarett                    }
1019741143878b23d22cd9cb7b9cba8055179115ce17msarett                    // Skip a byte if necessary to maintain alignment
1020741143878b23d22cd9cb7b9cba8055179115ce17msarett                    if (!SkIsAlign2(rowBytes)) {
1021741143878b23d22cd9cb7b9cba8055179115ce17msarett                        currByte++;
1022741143878b23d22cd9cb7b9cba8055179115ce17msarett                    }
1023741143878b23d22cd9cb7b9cba8055179115ce17msarett                    break;
1024741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
1025741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
1026741143878b23d22cd9cb7b9cba8055179115ce17msarett        } else {
1027741143878b23d22cd9cb7b9cba8055179115ce17msarett            // If the first byte read is not a flag, it indicates the number of
1028741143878b23d22cd9cb7b9cba8055179115ce17msarett            // pixels to set in RLE mode.
1029741143878b23d22cd9cb7b9cba8055179115ce17msarett            const uint8_t numPixels = flag;
1030741143878b23d22cd9cb7b9cba8055179115ce17msarett            const int endX = SkTMin<int>(x + numPixels, width);
1031741143878b23d22cd9cb7b9cba8055179115ce17msarett
1032741143878b23d22cd9cb7b9cba8055179115ce17msarett            if (24 == fBitsPerPixel) {
1033741143878b23d22cd9cb7b9cba8055179115ce17msarett                // In RLE24, the second byte read is part of the pixel color.
1034741143878b23d22cd9cb7b9cba8055179115ce17msarett                // There are two more required bytes to finish encoding the
1035741143878b23d22cd9cb7b9cba8055179115ce17msarett                // color.
1036741143878b23d22cd9cb7b9cba8055179115ce17msarett                if ((int) totalBytes - currByte < 2) {
1037230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                    SkCodecPrintf("Warning: incomplete RLE input\n");
1038741143878b23d22cd9cb7b9cba8055179115ce17msarett                    return kIncompleteInput;
1039741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
1040741143878b23d22cd9cb7b9cba8055179115ce17msarett
1041741143878b23d22cd9cb7b9cba8055179115ce17msarett                // Fill the pixels up to endX with the specified color
1042741143878b23d22cd9cb7b9cba8055179115ce17msarett                uint8_t blue = task;
1043741143878b23d22cd9cb7b9cba8055179115ce17msarett                uint8_t green = buffer.get()[currByte++];
1044741143878b23d22cd9cb7b9cba8055179115ce17msarett                uint8_t red = buffer.get()[currByte++];
1045741143878b23d22cd9cb7b9cba8055179115ce17msarett                while (x < endX) {
1046438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                    setRLE24Pixel(dst, dstRowBytes, dstInfo, x++, y, red,
1047eed039b5ffbdff958053ac80b09451ad6caa1787msarett                            green, blue);
1048741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
1049741143878b23d22cd9cb7b9cba8055179115ce17msarett            } else {
1050741143878b23d22cd9cb7b9cba8055179115ce17msarett                // In RLE8 or RLE4, the second byte read gives the index in the
1051741143878b23d22cd9cb7b9cba8055179115ce17msarett                // color table to look up the pixel color.
1052741143878b23d22cd9cb7b9cba8055179115ce17msarett                // RLE8 has one color index that gets repeated
1053741143878b23d22cd9cb7b9cba8055179115ce17msarett                // RLE4 has two color indexes in the upper and lower 4 bits of
1054741143878b23d22cd9cb7b9cba8055179115ce17msarett                // the bytes, which are alternated
1055741143878b23d22cd9cb7b9cba8055179115ce17msarett                uint8_t indices[2] = { task, task };
1056741143878b23d22cd9cb7b9cba8055179115ce17msarett                if (4 == fBitsPerPixel) {
1057741143878b23d22cd9cb7b9cba8055179115ce17msarett                    indices[0] >>= 4;
1058741143878b23d22cd9cb7b9cba8055179115ce17msarett                    indices[1] &= 0xf;
1059741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
1060741143878b23d22cd9cb7b9cba8055179115ce17msarett
1061741143878b23d22cd9cb7b9cba8055179115ce17msarett                // Set the indicated number of pixels
1062741143878b23d22cd9cb7b9cba8055179115ce17msarett                for (int which = 0; x < endX; x++) {
1063438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                    setRLEPixel(dst, dstRowBytes, dstInfo, x, y,
1064741143878b23d22cd9cb7b9cba8055179115ce17msarett                            indices[which]);
1065741143878b23d22cd9cb7b9cba8055179115ce17msarett                    which = !which;
1066741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
1067741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
1068741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
1069741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
1070741143878b23d22cd9cb7b9cba8055179115ce17msarett}
1071741143878b23d22cd9cb7b9cba8055179115ce17msarett
1072741143878b23d22cd9cb7b9cba8055179115ce17msarett/*
1073741143878b23d22cd9cb7b9cba8055179115ce17msarett *
1074741143878b23d22cd9cb7b9cba8055179115ce17msarett * Performs the bitmap decoding for standard input format
1075741143878b23d22cd9cb7b9cba8055179115ce17msarett *
1076741143878b23d22cd9cb7b9cba8055179115ce17msarett */
1077741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
10783c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett                                   void* dst, size_t dstRowBytes,
10793c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett                                   const Options& opts) {
1080741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Set constant values
1081741143878b23d22cd9cb7b9cba8055179115ce17msarett    const int width = dstInfo.width();
1082741143878b23d22cd9cb7b9cba8055179115ce17msarett    const int height = dstInfo.height();
1083741143878b23d22cd9cb7b9cba8055179115ce17msarett    const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
1084741143878b23d22cd9cb7b9cba8055179115ce17msarett
1085e16b04aa6041efb6507546547737e9603fa1606emsarett    // Get swizzler configuration and choose the fill value for failures.  We will use
1086e16b04aa6041efb6507546547737e9603fa1606emsarett    // zero as the default palette index, black for opaque images, and transparent for
1087e16b04aa6041efb6507546547737e9603fa1606emsarett    // non-opaque images.
1088741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkSwizzler::SrcConfig config;
1089e16b04aa6041efb6507546547737e9603fa1606emsarett    uint32_t fillColorOrIndex;
1090e16b04aa6041efb6507546547737e9603fa1606emsarett    bool zeroFill = true;
1091741143878b23d22cd9cb7b9cba8055179115ce17msarett    switch (fBitsPerPixel) {
1092741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 1:
1093741143878b23d22cd9cb7b9cba8055179115ce17msarett            config = SkSwizzler::kIndex1;
1094e16b04aa6041efb6507546547737e9603fa1606emsarett            fillColorOrIndex = 0;
1095741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
1096741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 2:
1097741143878b23d22cd9cb7b9cba8055179115ce17msarett            config = SkSwizzler::kIndex2;
1098e16b04aa6041efb6507546547737e9603fa1606emsarett            fillColorOrIndex = 0;
1099741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
1100741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 4:
1101741143878b23d22cd9cb7b9cba8055179115ce17msarett            config = SkSwizzler::kIndex4;
1102e16b04aa6041efb6507546547737e9603fa1606emsarett            fillColorOrIndex = 0;
1103741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
1104741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 8:
1105741143878b23d22cd9cb7b9cba8055179115ce17msarett            config = SkSwizzler::kIndex;
1106e16b04aa6041efb6507546547737e9603fa1606emsarett            fillColorOrIndex = 0;
1107741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
1108741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 24:
1109741143878b23d22cd9cb7b9cba8055179115ce17msarett            config = SkSwizzler::kBGR;
1110e16b04aa6041efb6507546547737e9603fa1606emsarett            fillColorOrIndex = SK_ColorBLACK;
1111e16b04aa6041efb6507546547737e9603fa1606emsarett            zeroFill = false;
1112741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
1113741143878b23d22cd9cb7b9cba8055179115ce17msarett        case 32:
1114eed039b5ffbdff958053ac80b09451ad6caa1787msarett            if (kOpaque_SkAlphaType == dstInfo.alphaType()) {
1115741143878b23d22cd9cb7b9cba8055179115ce17msarett                config = SkSwizzler::kBGRX;
1116e16b04aa6041efb6507546547737e9603fa1606emsarett                fillColorOrIndex = SK_ColorBLACK;
1117e16b04aa6041efb6507546547737e9603fa1606emsarett                zeroFill = false;
1118741143878b23d22cd9cb7b9cba8055179115ce17msarett            } else {
1119741143878b23d22cd9cb7b9cba8055179115ce17msarett                config = SkSwizzler::kBGRA;
1120e16b04aa6041efb6507546547737e9603fa1606emsarett                fillColorOrIndex = SK_ColorTRANSPARENT;
1121741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
1122741143878b23d22cd9cb7b9cba8055179115ce17msarett            break;
1123741143878b23d22cd9cb7b9cba8055179115ce17msarett        default:
1124741143878b23d22cd9cb7b9cba8055179115ce17msarett            SkASSERT(false);
1125741143878b23d22cd9cb7b9cba8055179115ce17msarett            return kInvalidInput;
1126741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
1127741143878b23d22cd9cb7b9cba8055179115ce17msarett
11283c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett    // Get a pointer to the color table if it exists
11293c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett    const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readColors() : NULL;
11303c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett
1131741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Create swizzler
1132eed039b5ffbdff958053ac80b09451ad6caa1787msarett    SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
11333c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            colorPtr, dstInfo, dst, dstRowBytes,
1134eed039b5ffbdff958053ac80b09451ad6caa1787msarett            SkImageGenerator::kNo_ZeroInitialized));
1135741143878b23d22cd9cb7b9cba8055179115ce17msarett
1136741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Allocate space for a row buffer and a source for the swizzler
1137741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
1138741143878b23d22cd9cb7b9cba8055179115ce17msarett
1139741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Iterate over rows of the image
1140741143878b23d22cd9cb7b9cba8055179115ce17msarett    // FIXME: bool transparent = true;
1141741143878b23d22cd9cb7b9cba8055179115ce17msarett    for (int y = 0; y < height; y++) {
1142741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Read a row of the input
1143741143878b23d22cd9cb7b9cba8055179115ce17msarett        if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1144230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo            SkCodecPrintf("Warning: incomplete input stream.\n");
11453c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            // Fill the destination image on failure
1146e16b04aa6041efb6507546547737e9603fa1606emsarett            if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) {
11473c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett                void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrder);
1148e16b04aa6041efb6507546547737e9603fa1606emsarett                SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y,
1149e16b04aa6041efb6507546547737e9603fa1606emsarett                        fillColorOrIndex, colorPtr);
11503c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett            }
1151741143878b23d22cd9cb7b9cba8055179115ce17msarett            return kIncompleteInput;
1152741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
1153741143878b23d22cd9cb7b9cba8055179115ce17msarett
1154741143878b23d22cd9cb7b9cba8055179115ce17msarett        // Decode the row in destination format
1155741143878b23d22cd9cb7b9cba8055179115ce17msarett        uint32_t row;
1156741143878b23d22cd9cb7b9cba8055179115ce17msarett        if (kTopDown_RowOrder == fRowOrder) {
1157741143878b23d22cd9cb7b9cba8055179115ce17msarett            row = y;
1158741143878b23d22cd9cb7b9cba8055179115ce17msarett        } else {
1159741143878b23d22cd9cb7b9cba8055179115ce17msarett            row = height - 1 - y;
1160741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
1161741143878b23d22cd9cb7b9cba8055179115ce17msarett
1162741143878b23d22cd9cb7b9cba8055179115ce17msarett        swizzler->next(srcBuffer.get(), row);
1163741143878b23d22cd9cb7b9cba8055179115ce17msarett        // FIXME: SkSwizzler::ResultAlpha r =
1164741143878b23d22cd9cb7b9cba8055179115ce17msarett        //        swizzler->next(srcBuffer.get(), row);
1165741143878b23d22cd9cb7b9cba8055179115ce17msarett        // FIXME: transparent &= SkSwizzler::IsTransparent(r);
1166741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
1167741143878b23d22cd9cb7b9cba8055179115ce17msarett
1168741143878b23d22cd9cb7b9cba8055179115ce17msarett    // FIXME: This code exists to match the behavior in the chromium decoder
1169741143878b23d22cd9cb7b9cba8055179115ce17msarett    // and to follow the bmp specification as it relates to alpha masks.  It is
1170741143878b23d22cd9cb7b9cba8055179115ce17msarett    // commented out because we have yet to discover a test image that provides
1171741143878b23d22cd9cb7b9cba8055179115ce17msarett    // an alpha mask and uses this decode mode.
1172741143878b23d22cd9cb7b9cba8055179115ce17msarett
1173741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Now we adjust the output image with some additional behavior that
1174741143878b23d22cd9cb7b9cba8055179115ce17msarett    // SkSwizzler does not support.  Firstly, all bmp images that contain
1175741143878b23d22cd9cb7b9cba8055179115ce17msarett    // alpha are masked by the alpha mask.  Secondly, many fully transparent
1176438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // bmp images are intended to be opaque.  Here, we make those corrections
1177438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // in the kN32 case.
1178741143878b23d22cd9cb7b9cba8055179115ce17msarett    /*
1179741143878b23d22cd9cb7b9cba8055179115ce17msarett    SkPMColor* dstRow = (SkPMColor*) dst;
1180741143878b23d22cd9cb7b9cba8055179115ce17msarett    if (SkSwizzler::kBGRA == config) {
1181741143878b23d22cd9cb7b9cba8055179115ce17msarett        for (int y = 0; y < height; y++) {
1182741143878b23d22cd9cb7b9cba8055179115ce17msarett            for (int x = 0; x < width; x++) {
1183741143878b23d22cd9cb7b9cba8055179115ce17msarett                if (transparent) {
1184741143878b23d22cd9cb7b9cba8055179115ce17msarett                    dstRow[x] |= 0xFF000000;
1185741143878b23d22cd9cb7b9cba8055179115ce17msarett                } else {
1186741143878b23d22cd9cb7b9cba8055179115ce17msarett                    dstRow[x] &= alphaMask;
1187741143878b23d22cd9cb7b9cba8055179115ce17msarett                }
1188741143878b23d22cd9cb7b9cba8055179115ce17msarett                dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
1189741143878b23d22cd9cb7b9cba8055179115ce17msarett            }
1190741143878b23d22cd9cb7b9cba8055179115ce17msarett        }
1191741143878b23d22cd9cb7b9cba8055179115ce17msarett    }
1192741143878b23d22cd9cb7b9cba8055179115ce17msarett    */
1193741143878b23d22cd9cb7b9cba8055179115ce17msarett
11949bde918754bc292469d801f156f3b626eb3db780msarett    // Finally, apply the AND mask for bmp-in-ico images
11959bde918754bc292469d801f156f3b626eb3db780msarett    if (fIsIco) {
11969bde918754bc292469d801f156f3b626eb3db780msarett        // The AND mask is always 1 bit per pixel
11979bde918754bc292469d801f156f3b626eb3db780msarett        const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
11989bde918754bc292469d801f156f3b626eb3db780msarett
11999bde918754bc292469d801f156f3b626eb3db780msarett        SkPMColor* dstPtr = (SkPMColor*) dst;
12009bde918754bc292469d801f156f3b626eb3db780msarett        for (int y = 0; y < height; y++) {
12019bde918754bc292469d801f156f3b626eb3db780msarett            // The srcBuffer will at least be large enough
12029bde918754bc292469d801f156f3b626eb3db780msarett            if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1203230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo                SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
12049bde918754bc292469d801f156f3b626eb3db780msarett                return kIncompleteInput;
12059bde918754bc292469d801f156f3b626eb3db780msarett            }
12069bde918754bc292469d801f156f3b626eb3db780msarett
12079bde918754bc292469d801f156f3b626eb3db780msarett            int row;
12089bde918754bc292469d801f156f3b626eb3db780msarett            if (kBottomUp_RowOrder == fRowOrder) {
12099bde918754bc292469d801f156f3b626eb3db780msarett                row = height - y - 1;
12109bde918754bc292469d801f156f3b626eb3db780msarett            } else {
12119bde918754bc292469d801f156f3b626eb3db780msarett                row = y;
12129bde918754bc292469d801f156f3b626eb3db780msarett            }
12139bde918754bc292469d801f156f3b626eb3db780msarett
12149bde918754bc292469d801f156f3b626eb3db780msarett            SkPMColor* dstRow =
12159bde918754bc292469d801f156f3b626eb3db780msarett                    SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
12169bde918754bc292469d801f156f3b626eb3db780msarett
12179bde918754bc292469d801f156f3b626eb3db780msarett            for (int x = 0; x < width; x++) {
12189bde918754bc292469d801f156f3b626eb3db780msarett                int quotient;
12199bde918754bc292469d801f156f3b626eb3db780msarett                int modulus;
12209bde918754bc292469d801f156f3b626eb3db780msarett                SkTDivMod(x, 8, &quotient, &modulus);
12219bde918754bc292469d801f156f3b626eb3db780msarett                uint32_t shift = 7 - modulus;
12229bde918754bc292469d801f156f3b626eb3db780msarett                uint32_t alphaBit =
12239bde918754bc292469d801f156f3b626eb3db780msarett                        (srcBuffer.get()[quotient] >> shift) & 0x1;
12249bde918754bc292469d801f156f3b626eb3db780msarett                dstRow[x] &= alphaBit - 1;
12259bde918754bc292469d801f156f3b626eb3db780msarett            }
12269bde918754bc292469d801f156f3b626eb3db780msarett        }
12279bde918754bc292469d801f156f3b626eb3db780msarett    }
12289bde918754bc292469d801f156f3b626eb3db780msarett
1229741143878b23d22cd9cb7b9cba8055179115ce17msarett    // Finished decoding the entire image
1230741143878b23d22cd9cb7b9cba8055179115ce17msarett    return kSuccess;
1231741143878b23d22cd9cb7b9cba8055179115ce17msarett}
1232