
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Test.h"
#include "SkBitmap.h"
#include "SkRect.h"

static const char* boolStr(bool value) {
    return value ? "true" : "false";
}

// these are in the same order as the SkBitmap::Config enum
static const char* gConfigName[] = {
    "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
};

static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src,
                              const SkBitmap& dst) {
    SkString str;
    str.printf("src %s opaque:%d, dst %s opaque:%d",
               gConfigName[src.config()], src.isOpaque(),
               gConfigName[dst.config()], dst.isOpaque());
    reporter->reportFailed(str);
}

static bool canHaveAlpha(SkBitmap::Config config) {
    return config != SkBitmap::kRGB_565_Config;
}

// copyTo() should preserve isOpaque when it makes sense
static void test_isOpaque(skiatest::Reporter* reporter, const SkBitmap& src,
                          SkBitmap::Config dstConfig) {
    SkBitmap bitmap(src);
    SkBitmap dst;

    // we need the lock so that we get a valid colorTable (when available)
    SkAutoLockPixels alp(bitmap);
    SkColorTable* ctable = bitmap.getColorTable();
    unsigned ctableFlags = ctable ? ctable->getFlags() : 0;

    if (canHaveAlpha(bitmap.config()) && canHaveAlpha(dstConfig)) {
        bitmap.setIsOpaque(false);
        if (ctable) {
            ctable->setFlags(ctableFlags & ~SkColorTable::kColorsAreOpaque_Flag);
        }
        REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig));
        REPORTER_ASSERT(reporter, dst.config() == dstConfig);
        if (bitmap.isOpaque() != dst.isOpaque()) {
            report_opaqueness(reporter, bitmap, dst);
        }
    }

    bitmap.setIsOpaque(true);
    if (ctable) {
        ctable->setFlags(ctableFlags | SkColorTable::kColorsAreOpaque_Flag);
    }
    REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig));
    REPORTER_ASSERT(reporter, dst.config() == dstConfig);
    if (bitmap.isOpaque() != dst.isOpaque()) {
        report_opaqueness(reporter, bitmap, dst);
    }

    if (ctable) {
        ctable->setFlags(ctableFlags);
    }
}

static void init_src(const SkBitmap& bitmap, const SkColorTable* ct) {
    SkAutoLockPixels lock(bitmap);
    if (bitmap.getPixels()) {
        if (ct) {
            sk_bzero(bitmap.getPixels(), bitmap.getSize());
        } else {
            bitmap.eraseColor(SK_ColorWHITE);
        }
    }
}

static SkColorTable* init_ctable() {
    static const SkColor colors[] = {
        SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE
    };
    return new SkColorTable(colors, SK_ARRAY_COUNT(colors));
}

struct Pair {
    SkBitmap::Config    fConfig;
    const char*         fValid;
};

// Utility functions for copyPixelsTo()/copyPixelsFrom() tests.
// getPixel()
// setPixel()
// getSkConfigName()
// struct Coordinates
// reportCopyVerification()
// writeCoordPixels()

// Utility function to read the value of a given pixel in bm. All
// values converted to uint32_t for simplification of comparisons.
static uint32_t getPixel(int x, int y, const SkBitmap& bm) {
    uint32_t val = 0;
    uint16_t val16;
    uint8_t val8, shift;
    SkAutoLockPixels lock(bm);
    const void* rawAddr = bm.getAddr(x,y);

    switch (bm.getConfig()) {
        case SkBitmap::kARGB_8888_Config:
            memcpy(&val, rawAddr, sizeof(uint32_t));
            break;
        case SkBitmap::kARGB_4444_Config:
        case SkBitmap::kRGB_565_Config:
            memcpy(&val16, rawAddr, sizeof(uint16_t));
            val = val16;
            break;
        case SkBitmap::kA8_Config:
        case SkBitmap::kIndex8_Config:
            memcpy(&val8, rawAddr, sizeof(uint8_t));
            val = val8;
            break;
        case SkBitmap::kA1_Config:
            memcpy(&val8, rawAddr, sizeof(uint8_t));
            shift = x % 8;
            val = (val8 >> shift) & 0x1 ;
            break;
        default:
            break;
    }
    return val;
}

// Utility function to set value of any pixel in bm.
// bm.getConfig() specifies what format 'val' must be
// converted to, but at present uint32_t can handle all formats.
static void setPixel(int x, int y, uint32_t val, SkBitmap& bm) {
    uint16_t val16;
    uint8_t val8, shift;
    SkAutoLockPixels lock(bm);
    void* rawAddr = bm.getAddr(x,y);

    switch (bm.getConfig()) {
        case SkBitmap::kARGB_8888_Config:
            memcpy(rawAddr, &val, sizeof(uint32_t));
            break;
        case SkBitmap::kARGB_4444_Config:
        case SkBitmap::kRGB_565_Config:
            val16 = val & 0xFFFF;
            memcpy(rawAddr, &val16, sizeof(uint16_t));
            break;
        case SkBitmap::kA8_Config:
        case SkBitmap::kIndex8_Config:
            val8 = val & 0xFF;
            memcpy(rawAddr, &val8, sizeof(uint8_t));
            break;
        case SkBitmap::kA1_Config:
            shift = x % 8; // We assume we're in the right byte.
            memcpy(&val8, rawAddr, sizeof(uint8_t));
            if (val & 0x1) // Turn bit on.
                val8 |= (0x1 << shift);
            else // Turn bit off.
                val8 &= ~(0x1 << shift);
            memcpy(rawAddr, &val8, sizeof(uint8_t));
            break;
        default:
            // Ignore.
            break;
    }
}

// Utility to return string containing name of each format, to
// simplify diagnostic output.
static const char* getSkConfigName(const SkBitmap& bm) {
    switch (bm.getConfig()) {
        case SkBitmap::kNo_Config: return "SkBitmap::kNo_Config";
        case SkBitmap::kA1_Config: return "SkBitmap::kA1_Config";
        case SkBitmap::kA8_Config: return "SkBitmap::kA8_Config";
        case SkBitmap::kIndex8_Config: return "SkBitmap::kIndex8_Config";
        case SkBitmap::kRGB_565_Config: return "SkBitmap::kRGB_565_Config";
        case SkBitmap::kARGB_4444_Config: return "SkBitmap::kARGB_4444_Config";
        case SkBitmap::kARGB_8888_Config: return "SkBitmap::kARGB_8888_Config";
        case SkBitmap::kRLE_Index8_Config:
            return "SkBitmap::kRLE_Index8_Config,";
        default: return "Unknown SkBitmap configuration.";
    }
}

// Helper struct to contain pixel locations, while avoiding need for STL.
struct Coordinates {

    const int length;
    SkIPoint* const data;

    explicit Coordinates(int _length): length(_length)
                                     , data(new SkIPoint[length]) { }

    ~Coordinates(){
        delete [] data;
    }

    SkIPoint* operator[](int i) const {
        // Use with care, no bounds checking.
        return data + i;
    }
};

// A function to verify that two bitmaps contain the same pixel values
// at all coordinates indicated by coords. Simplifies verification of
// copied bitmaps.
static void reportCopyVerification(const SkBitmap& bm1, const SkBitmap& bm2,
                            Coordinates& coords,
                            const char* msg,
                            skiatest::Reporter* reporter){
    bool success = true;

    // Confirm all pixels in the list match.
    for (int i = 0; i < coords.length; ++i) {
        success = success &&
                  (getPixel(coords[i]->fX, coords[i]->fY, bm1) ==
                   getPixel(coords[i]->fX, coords[i]->fY, bm2));
    }

    if (!success) {
        SkString str;
        str.printf("%s [config = %s]",
                   msg, getSkConfigName(bm1));
        reporter->reportFailed(str);
    }
}

// Writes unique pixel values at locations specified by coords.
static void writeCoordPixels(SkBitmap& bm, const Coordinates& coords) {
    for (int i = 0; i < coords.length; ++i)
        setPixel(coords[i]->fX, coords[i]->fY, i, bm);
}

static void TestBitmapCopy(skiatest::Reporter* reporter) {
    static const Pair gPairs[] = {
        { SkBitmap::kNo_Config,         "00000000"  },
        { SkBitmap::kA1_Config,         "01000000"  },
        { SkBitmap::kA8_Config,         "00101110"  },
        { SkBitmap::kIndex8_Config,     "00111110"  },
        { SkBitmap::kRGB_565_Config,    "00101110"  },
        { SkBitmap::kARGB_4444_Config,  "00101110"  },
        { SkBitmap::kARGB_8888_Config,  "00101110"  },
// TODO: create valid RLE bitmap to test with
 //       { SkBitmap::kRLE_Index8_Config, "00101111"  }
    };

    static const bool isExtracted[] = {
        false, true
    };

    const int W = 20;
    const int H = 33;

    for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
        for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
            SkBitmap src, dst;
            SkColorTable* ct = NULL;

            src.setConfig(gPairs[i].fConfig, W, H);
            if (SkBitmap::kIndex8_Config == src.config() ||
                    SkBitmap::kRLE_Index8_Config == src.config()) {
                ct = init_ctable();
            }
            src.allocPixels(ct);
            SkSafeUnref(ct);

            init_src(src, ct);
            bool success = src.copyTo(&dst, gPairs[j].fConfig);
            bool expected = gPairs[i].fValid[j] != '0';
            if (success != expected) {
                SkString str;
                str.printf("SkBitmap::copyTo from %s to %s. expected %s returned %s",
                           gConfigName[i], gConfigName[j], boolStr(expected),
                           boolStr(success));
                reporter->reportFailed(str);
            }

            bool canSucceed = src.canCopyTo(gPairs[j].fConfig);
            if (success != canSucceed) {
                SkString str;
                str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyTo %s",
                           gConfigName[i], gConfigName[j], boolStr(success),
                           boolStr(canSucceed));
                reporter->reportFailed(str);
            }

            if (success) {
                REPORTER_ASSERT(reporter, src.width() == dst.width());
                REPORTER_ASSERT(reporter, src.height() == dst.height());
                REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig);
                test_isOpaque(reporter, src, dst.config());
                if (src.config() == dst.config()) {
                    SkAutoLockPixels srcLock(src);
                    SkAutoLockPixels dstLock(dst);
                    REPORTER_ASSERT(reporter, src.readyToDraw());
                    REPORTER_ASSERT(reporter, dst.readyToDraw());
                    const char* srcP = (const char*)src.getAddr(0, 0);
                    const char* dstP = (const char*)dst.getAddr(0, 0);
                    REPORTER_ASSERT(reporter, srcP != dstP);
                    REPORTER_ASSERT(reporter, !memcmp(srcP, dstP,
                                                      src.getSize()));
                    REPORTER_ASSERT(reporter, src.getGenerationID() == dst.getGenerationID());
                } else {
                    REPORTER_ASSERT(reporter, src.getGenerationID() != dst.getGenerationID());
                }
                // test extractSubset
                {
                    SkBitmap bitmap(src);
                    SkBitmap subset;
                    SkIRect r;
                    r.set(1, 1, 2, 2);
                    bitmap.setIsOpaque(true);
                    bitmap.setIsVolatile(true);
                    if (bitmap.extractSubset(&subset, r)) {
                        REPORTER_ASSERT(reporter, subset.width() == 1);
                        REPORTER_ASSERT(reporter, subset.height() == 1);
                        REPORTER_ASSERT(reporter,
                                        subset.isOpaque() == bitmap.isOpaque());
                        REPORTER_ASSERT(reporter,
                                        subset.isVolatile() == true);

                        SkBitmap copy;
                        REPORTER_ASSERT(reporter,
                                        subset.copyTo(&copy, subset.config()));
                        REPORTER_ASSERT(reporter, copy.width() == 1);
                        REPORTER_ASSERT(reporter, copy.height() == 1);
                        REPORTER_ASSERT(reporter, copy.rowBytes() <= 4);

                        SkAutoLockPixels alp0(subset);
                        SkAutoLockPixels alp1(copy);
                        // they should both have, or both not-have, a colortable
                        bool hasCT = subset.getColorTable() != NULL;
                        REPORTER_ASSERT(reporter,
                                    (copy.getColorTable() != NULL) == hasCT);
                    }
                    bitmap.setIsOpaque(false);
                    bitmap.setIsVolatile(false);
                    if (bitmap.extractSubset(&subset, r)) {
                        REPORTER_ASSERT(reporter,
                                        subset.isOpaque() == bitmap.isOpaque());
                        REPORTER_ASSERT(reporter,
                                        subset.isVolatile() == false);
                    }
                }
            } else {
                // dst should be unchanged from its initial state
                REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config);
                REPORTER_ASSERT(reporter, dst.width() == 0);
                REPORTER_ASSERT(reporter, dst.height() == 0);
            }
        } // for (size_t j = ...

        // Tests for getSafeSize(), getSafeSize64(), copyPixelsTo(),
        // copyPixelsFrom().
        //
        for (size_t copyCase = 0; copyCase < SK_ARRAY_COUNT(isExtracted);
             ++copyCase) {
            // Test copying to/from external buffer.
            // Note: the tests below have hard-coded values ---
            //       Please take care if modifying.
            if (gPairs[i].fConfig != SkBitmap::kRLE_Index8_Config) {

                // Tests for getSafeSize64().
                // Test with a very large configuration without pixel buffer
                // attached.
                SkBitmap tstSafeSize;
                tstSafeSize.setConfig(gPairs[i].fConfig, 100000000U,
                                      100000000U);
                Sk64 safeSize = tstSafeSize.getSafeSize64();
                if (safeSize.isNeg()) {
                    SkString str;
                    str.printf("getSafeSize64() negative: %s",
                        getSkConfigName(tstSafeSize));
                    reporter->reportFailed(str);
                }
                bool sizeFail = false;
                // Compare against hand-computed values.
                switch (gPairs[i].fConfig) {
                    case SkBitmap::kNo_Config:
                        break;

                    case SkBitmap::kA1_Config:
                        if (safeSize.fHi != 0x470DE ||
                            safeSize.fLo != 0x4DF82000)
                            sizeFail = true;
                        break;

                    case SkBitmap::kA8_Config:
                    case SkBitmap::kIndex8_Config:
                        if (safeSize.fHi != 0x2386F2 ||
                            safeSize.fLo != 0x6FC10000)
                            sizeFail = true;
                        break;

                    case SkBitmap::kRGB_565_Config:
                    case SkBitmap::kARGB_4444_Config:
                        if (safeSize.fHi != 0x470DE4 ||
                            safeSize.fLo != 0xDF820000)
                            sizeFail = true;
                        break;

                    case SkBitmap::kARGB_8888_Config:
                        if (safeSize.fHi != 0x8E1BC9 ||
                            safeSize.fLo != 0xBF040000)
                            sizeFail = true;
                        break;

                    case SkBitmap::kRLE_Index8_Config:
                        break;

                    default:
                        break;
                }
                if (sizeFail) {
                    SkString str;
                    str.printf("getSafeSize64() wrong size: %s",
                        getSkConfigName(tstSafeSize));
                    reporter->reportFailed(str);
                }

                size_t subW, subH;
                // Set sizes to be height = 2 to force the last row of the
                // source to be used, thus verifying correct operation if
                // the bitmap is an extracted subset.
                if (gPairs[i].fConfig == SkBitmap::kA1_Config) {
                    // If one-bit per pixel, use 9 pixels to force more than
                    // one byte per row.
                    subW = 9;
                    subH = 2;
                } else {
                    // All other configurations are at least one byte per pixel,
                    // and different configs will test copying different numbers
                    // of bytes.
                    subW = subH = 2;
                }

                // Create bitmap to act as source for copies and subsets.
                SkBitmap src, subset;
                SkColorTable* ct = NULL;
                if (isExtracted[copyCase]) { // A larger image to extract from.
                    src.setConfig(gPairs[i].fConfig, 2 * subW + 1, subH);
                } else // Tests expect a 2x2 bitmap, so make smaller.
                    src.setConfig(gPairs[i].fConfig, subW, subH);
                if (SkBitmap::kIndex8_Config == src.config() ||
                        SkBitmap::kRLE_Index8_Config == src.config()) {
                    ct = init_ctable();
                }

                src.allocPixels(ct);
                SkSafeUnref(ct);

                // Either copy src or extract into 'subset', which is used
                // for subsequent calls to copyPixelsTo/From.
                bool srcReady = false;
                if (isExtracted[copyCase]) {
                    // The extractedSubset() test case allows us to test copy-
                    // ing when src and dst mave possibly different strides.
                    SkIRect r;
                    if (gPairs[i].fConfig == SkBitmap::kA1_Config)
                        // This config seems to need byte-alignment of
                        // extracted subset bits.
                        r.set(0, 0, subW, subH);
                    else
                        r.set(1, 0, 1 + subW, subH); // 2x2 extracted bitmap

                    srcReady = src.extractSubset(&subset, r);
                } else {
                    srcReady = src.copyTo(&subset, src.getConfig());
                }

                // Not all configurations will generate a valid 'subset'.
                if (srcReady) {

                    // Allocate our target buffer 'buf' for all copies.
                    // To simplify verifying correctness of copies attach
                    // buf to a SkBitmap, but copies are done using the
                    // raw buffer pointer.
                    const uint32_t bufSize = subH *
                        SkBitmap::ComputeRowBytes(src.getConfig(), subW) * 2;
                    SkAutoMalloc autoBuf (bufSize);
                    uint8_t* buf = static_cast<uint8_t*>(autoBuf.get());

                    SkBitmap bufBm; // Attach buf to this bitmap.
                    bool successExpected;

                    // Set up values for each pixel being copied.
                    Coordinates coords(subW * subH);
                    for (size_t x = 0; x < subW; ++x)
                        for (size_t y = 0; y < subH; ++y)
                        {
                            int index = y * subW + x;
                            SkASSERT(index < coords.length);
                            coords[index]->fX = x;
                            coords[index]->fY = y;
                        }

                    writeCoordPixels(subset, coords);

                    // Test #1 ////////////////////////////////////////////

                    // Before/after comparisons easier if we attach buf
                    // to an appropriately configured SkBitmap.
                    memset(buf, 0xFF, bufSize);
                    // Config with stride greater than src but that fits in buf.
                    bufBm.setConfig(gPairs[i].fConfig, subW, subH,
                        SkBitmap::ComputeRowBytes(subset.getConfig(), subW)
                                                  * 2);
                    bufBm.setPixels(buf);
                    successExpected = false;
                    // Then attempt to copy with a stride that is too large
                    // to fit in the buffer.
                    REPORTER_ASSERT(reporter,
                        subset.copyPixelsTo(buf, bufSize, bufBm.rowBytes() * 3)
                        == successExpected);

                    if (successExpected)
                        reportCopyVerification(subset, bufBm, coords,
                            "copyPixelsTo(buf, bufSize, 1.5*maxRowBytes)",
                            reporter);

                    // Test #2 ////////////////////////////////////////////
                    // This test should always succeed, but in the case
                    // of extracted bitmaps only because we handle the
                    // issue of getSafeSize(). Without getSafeSize()
                    // buffer overrun/read would occur.
                    memset(buf, 0xFF, bufSize);
                    bufBm.setConfig(gPairs[i].fConfig, subW, subH,
                                    subset.rowBytes());
                    bufBm.setPixels(buf);
                    successExpected = subset.getSafeSize() <= bufSize;
                    REPORTER_ASSERT(reporter,
                        subset.copyPixelsTo(buf, bufSize) ==
                            successExpected);
                    if (successExpected)
                        reportCopyVerification(subset, bufBm, coords,
                        "copyPixelsTo(buf, bufSize)", reporter);

                    // Test #3 ////////////////////////////////////////////
                    // Copy with different stride between src and dst.
                    memset(buf, 0xFF, bufSize);
                    bufBm.setConfig(gPairs[i].fConfig, subW, subH,
                                    subset.rowBytes()+1);
                    bufBm.setPixels(buf);
                    successExpected = true; // Should always work.
                    REPORTER_ASSERT(reporter,
                            subset.copyPixelsTo(buf, bufSize,
                                subset.rowBytes()+1) == successExpected);
                    if (successExpected)
                        reportCopyVerification(subset, bufBm, coords,
                        "copyPixelsTo(buf, bufSize, rowBytes+1)", reporter);

                    // Test #4 ////////////////////////////////////////////
                    // Test copy with stride too small.
                    memset(buf, 0xFF, bufSize);
                    bufBm.setConfig(gPairs[i].fConfig, subW, subH);
                    bufBm.setPixels(buf);
                    successExpected = false;
                    // Request copy with stride too small.
                    REPORTER_ASSERT(reporter,
                        subset.copyPixelsTo(buf, bufSize, bufBm.rowBytes()-1)
                            == successExpected);
                    if (successExpected)
                        reportCopyVerification(subset, bufBm, coords,
                        "copyPixelsTo(buf, bufSize, rowBytes()-1)", reporter);

#if 0   // copyPixelsFrom is gone
                    // Test #5 ////////////////////////////////////////////
                    // Tests the case where the source stride is too small
                    // for the source configuration.
                    memset(buf, 0xFF, bufSize);
                    bufBm.setConfig(gPairs[i].fConfig, subW, subH);
                    bufBm.setPixels(buf);
                    writeCoordPixels(bufBm, coords);
                    REPORTER_ASSERT(reporter,
                        subset.copyPixelsFrom(buf, bufSize, 1) == false);

                    // Test #6 ///////////////////////////////////////////
                    // Tests basic copy from an external buffer to the bitmap.
                    // If the bitmap is "extracted", this also tests the case
                    // where the source stride is different from the dest.
                    // stride.
                    // We've made the buffer large enough to always succeed.
                    bufBm.setConfig(gPairs[i].fConfig, subW, subH);
                    bufBm.setPixels(buf);
                    writeCoordPixels(bufBm, coords);
                    REPORTER_ASSERT(reporter,
                        subset.copyPixelsFrom(buf, bufSize, bufBm.rowBytes()) ==
                            true);
                    reportCopyVerification(bufBm, subset, coords,
                        "copyPixelsFrom(buf, bufSize)",
                        reporter);

                    // Test #7 ////////////////////////////////////////////
                    // Tests the case where the source buffer is too small
                    // for the transfer.
                    REPORTER_ASSERT(reporter,
                        subset.copyPixelsFrom(buf, 1, subset.rowBytes()) ==
                            false);

#endif
                }
            }
        } // for (size_t copyCase ...
    }
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy)
