
/*
 * 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 "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkDevice.h"
#include "SkMathPriv.h"
#include "SkRegion.h"
#if SK_SUPPORT_GPU
#include "SkGpuDevice.h"
#endif


static const int DEV_W = 100, DEV_H = 100;
static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
static const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
                                                DEV_H * SK_Scalar1);

namespace {
SkPMColor getCanvasColor(int x, int y) {
    SkASSERT(x >= 0 && x < DEV_W);
    SkASSERT(y >= 0 && y < DEV_H);

    U8CPU r = x;
    U8CPU g = y;
    U8CPU b = 0xc;

    U8CPU a = 0xff;
    switch ((x+y) % 5) {
        case 0:
            a = 0xff;
            break;
        case 1:
            a = 0x80;
            break;
        case 2:
            a = 0xCC;
            break;
        case 4:
            a = 0x01;
            break;
        case 3:
            a = 0x00;
            break;
    }
    return SkPremultiplyARGBInline(a, r, g, b);
}

SkPMColor getBitmapColor(int x, int y, int w, int h) {
    int n = y * w + x;

    U8CPU b = n & 0xff;
    U8CPU g = (n >> 8) & 0xff;
    U8CPU r = (n >> 16) & 0xff;
    return SkPackARGB32(0xff, r, g , b);
}

SkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888,
                                     uint32_t color,
                                     bool* premul) {
    const uint8_t* c = reinterpret_cast<uint8_t*>(&color);
    U8CPU a,r,g,b;
    *premul = false;
    switch (config8888) {
        case SkCanvas::kNative_Premul_Config8888:
            return color;
        case SkCanvas::kNative_Unpremul_Config8888:
            *premul = true;
            a = SkGetPackedA32(color);
            r = SkGetPackedR32(color);
            g = SkGetPackedG32(color);
            b = SkGetPackedB32(color);
            break;
        case SkCanvas::kBGRA_Unpremul_Config8888:
            *premul = true; // fallthru
        case SkCanvas::kBGRA_Premul_Config8888:
            a = static_cast<U8CPU>(c[3]);
            r = static_cast<U8CPU>(c[2]);
            g = static_cast<U8CPU>(c[1]);
            b = static_cast<U8CPU>(c[0]);
            break;
        case SkCanvas::kRGBA_Unpremul_Config8888:
            *premul = true; // fallthru
        case SkCanvas::kRGBA_Premul_Config8888:
            a = static_cast<U8CPU>(c[3]);
            r = static_cast<U8CPU>(c[0]);
            g = static_cast<U8CPU>(c[1]);
            b = static_cast<U8CPU>(c[2]);
            break;
        default:
            SkDEBUGFAIL("Unexpected Config8888");
            return 0;
    }
    if (*premul) {
        r = SkMulDiv255Ceiling(r, a);
        g = SkMulDiv255Ceiling(g, a);
        b = SkMulDiv255Ceiling(b, a);
    }
    return SkPackARGB32(a, r, g, b);
}

void fillCanvas(SkCanvas* canvas) {
    static SkBitmap bmp;
    if (bmp.isNull()) {
        bmp.setConfig(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H);
        SkDEBUGCODE(bool alloc =) bmp.allocPixels();
        SkASSERT(alloc);
        SkAutoLockPixels alp(bmp);
        intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
        for (int y = 0; y < DEV_H; ++y) {
            for (int x = 0; x < DEV_W; ++x) {
                SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
                *pixel = getCanvasColor(x, y);
            }
        }
    }
    canvas->save();
    canvas->setMatrix(SkMatrix::I());
    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
    SkPaint paint;
    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    canvas->drawBitmap(bmp, 0, 0, &paint);
    canvas->restore();
}

void fillBitmap(SkBitmap* bitmap) {
    SkASSERT(bitmap->lockPixelsAreWritable());
    SkAutoLockPixels alp(*bitmap);
    int w = bitmap->width();
    int h = bitmap->height();
    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
    for (int y = 0; y < h; ++y) {
        for (int x = 0; x < w; ++x) {
            SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
            *pixel = getBitmapColor(x, y, w, h);
        }
    }
}

bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
    if (!didPremulConversion) {
        return a == b;
    }
    int32_t aA = static_cast<int32_t>(SkGetPackedA32(a));
    int32_t aR = static_cast<int32_t>(SkGetPackedR32(a));
    int32_t aG = static_cast<int32_t>(SkGetPackedG32(a));
    int32_t aB = SkGetPackedB32(a);

    int32_t bA = static_cast<int32_t>(SkGetPackedA32(b));
    int32_t bR = static_cast<int32_t>(SkGetPackedR32(b));
    int32_t bG = static_cast<int32_t>(SkGetPackedG32(b));
    int32_t bB = static_cast<int32_t>(SkGetPackedB32(b));

    return aA == bA &&
           SkAbs32(aR - bR) <= 1 &&
           SkAbs32(aG - bG) <= 1 &&
           SkAbs32(aB - bB) <= 1;
}

// checks the bitmap contains correct pixels after the readPixels
// if the bitmap was prefilled with pixels it checks that these weren't
// overwritten in the area outside the readPixels.
bool checkRead(skiatest::Reporter* reporter,
               const SkBitmap& bitmap,
               int x, int y,
               bool checkCanvasPixels,
               bool checkBitmapPixels,
               SkCanvas::Config8888 config8888) {
    SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
    SkASSERT(!bitmap.isNull());
    SkASSERT(checkCanvasPixels || checkBitmapPixels);

    int bw = bitmap.width();
    int bh = bitmap.height();

    SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh);
    SkIRect clippedSrcRect = DEV_RECT;
    if (!clippedSrcRect.intersect(srcRect)) {
        clippedSrcRect.setEmpty();
    }
    SkAutoLockPixels alp(bitmap);
    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap.getPixels());
    for (int by = 0; by < bh; ++by) {
        for (int bx = 0; bx < bw; ++bx) {
            int devx = bx + srcRect.fLeft;
            int devy = by + srcRect.fTop;

            uint32_t pixel = *reinterpret_cast<SkPMColor*>(pixels + by * bitmap.rowBytes() + bx * bitmap.bytesPerPixel());

            if (clippedSrcRect.contains(devx, devy)) {
                if (checkCanvasPixels) {
                    SkPMColor canvasPixel = getCanvasColor(devx, devy);
                    bool didPremul;
                    SkPMColor pmPixel = convertConfig8888ToPMColor(config8888, pixel, &didPremul);
                    bool check;
                    REPORTER_ASSERT(reporter, check = checkPixel(pmPixel, canvasPixel, didPremul));
                    if (!check) {
                        return false;
                    }
                }
            } else if (checkBitmapPixels) {
                REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw, bh) == pixel);
                if (getBitmapColor(bx, by, bw, bh) != pixel) {
                    return false;
                }
            }
        }
    }
    return true;
}

enum BitmapInit {
    kFirstBitmapInit = 0,

    kNoPixels_BitmapInit = kFirstBitmapInit,
    kTight_BitmapInit,
    kRowBytes_BitmapInit,

    kBitmapInitCnt
};

BitmapInit nextBMI(BitmapInit bmi) {
    int x = bmi;
    return static_cast<BitmapInit>(++x);
}


void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init) {
    int w = rect.width();
    int h = rect.height();
    int rowBytes = 0;
    bool alloc = true;
    switch (init) {
        case kNoPixels_BitmapInit:
            alloc = false;
        case kTight_BitmapInit:
            break;
        case kRowBytes_BitmapInit:
            rowBytes = w * sizeof(SkPMColor) + 16 * sizeof(SkPMColor);
            break;
        default:
            SkASSERT(0);
            break;
    }
    bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h, rowBytes);
    if (alloc) {
        bitmap->allocPixels();
    }
}

void ReadPixelsTest(skiatest::Reporter* reporter, GrContext* context) {
    const SkIRect testRects[] = {
        // entire thing
        DEV_RECT,
        // larger on all sides
        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
        // fully contained
        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
        // outside top left
        SkIRect::MakeLTRB(-10, -10, -1, -1),
        // touching top left corner
        SkIRect::MakeLTRB(-10, -10, 0, 0),
        // overlapping top left corner
        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
        // overlapping top left and top right corners
        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
        // touching entire top edge
        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
        // overlapping top right corner
        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
        // contained in x, overlapping top edge
        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
        // outside top right corner
        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
        // touching top right corner
        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
        // overlapping top left and bottom left corners
        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
        // touching entire left edge
        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
        // overlapping bottom left corner
        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
        // contained in y, overlapping left edge
        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
        // outside bottom left corner
        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
        // touching bottom left corner
        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
        // overlapping bottom left and bottom right corners
        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
        // touching entire left edge
        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
        // overlapping bottom right corner
        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
        // overlapping top right and bottom right corners
        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
    };

    for (int dtype = 0; dtype < 2; ++dtype) {
        SkAutoTUnref<SkDevice> device;
        if (0 == dtype) {
            device.reset(new SkDevice(SkBitmap::kARGB_8888_Config,
                                          DEV_W,
                                          DEV_H,
                                          false));
        } else {
// GPU device known not to work in the fixed pt build.
#if defined(SK_SCALAR_IS_FIXED) || !SK_SUPPORT_GPU
            continue;
#else
            device.reset(new SkGpuDevice(context,
                                             SkBitmap::kARGB_8888_Config,
                                             DEV_W,
                                             DEV_H));
#endif
        }
        SkCanvas canvas(device);
        fillCanvas(&canvas);

        static const SkCanvas::Config8888 gReadConfigs[] = {
            SkCanvas::kNative_Premul_Config8888,
            SkCanvas::kNative_Unpremul_Config8888,
/**
 * There is a bug in Ganesh (http://code.google.com/p/skia/issues/detail?id=438)
 * that causes the readback of pixels from BGRA canvas to an RGBA bitmap to
 * fail. This should be removed as soon as the issue above is resolved.
 */
#if !defined(SK_BUILD_FOR_ANDROID)
            SkCanvas::kBGRA_Premul_Config8888,
            SkCanvas::kBGRA_Unpremul_Config8888,
#endif
            SkCanvas::kRGBA_Premul_Config8888,
            SkCanvas::kRGBA_Unpremul_Config8888,
        };
        for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
            const SkIRect& srcRect = testRects[rect];
            for (BitmapInit bmi = kFirstBitmapInit;
                 bmi < kBitmapInitCnt;
                 bmi = nextBMI(bmi)) {
                for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) {
                    SkCanvas::Config8888 config8888 = gReadConfigs[c];
                    SkBitmap bmp;
                    init_bitmap(&bmp, srcRect, bmi);

                    // if the bitmap has pixels allocated before the readPixels,
                    // note that and fill them with pattern
                    bool startsWithPixels = !bmp.isNull();
                    if (startsWithPixels) {
                        fillBitmap(&bmp);
                    }
                    uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
                    bool success =
                        canvas.readPixels(&bmp, srcRect.fLeft,
                                          srcRect.fTop, config8888);
                    uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();

                    // we expect to succeed when the read isn't fully clipped
                    // out.
                    bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT);
                    // determine whether we expected the read to succeed.
                    REPORTER_ASSERT(reporter, success == expectSuccess);
                    // read pixels should never change the gen id
                    REPORTER_ASSERT(reporter, idBefore == idAfter);

                    if (success || startsWithPixels) {
                        checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop,
                                  success, startsWithPixels, config8888);
                    } else {
                        // if we had no pixels beforehand and the readPixels
                        // failed then our bitmap should still not have pixels
                        REPORTER_ASSERT(reporter, bmp.isNull());
                    }
                }
                // check the old webkit version of readPixels that clips the
                // bitmap size
                SkBitmap wkbmp;
                bool success = canvas.readPixels(srcRect, &wkbmp);
                SkIRect clippedRect = DEV_RECT;
                if (clippedRect.intersect(srcRect)) {
                    REPORTER_ASSERT(reporter, success);
                    checkRead(reporter, wkbmp, clippedRect.fLeft,
                              clippedRect.fTop, true, false,
                              SkCanvas::kNative_Premul_Config8888);
                } else {
                    REPORTER_ASSERT(reporter, !success);
                }
            }
        }
    }
}
}

#include "TestClassDef.h"
DEFINE_GPUTESTCLASS("ReadPixels", ReadPixelsTestClass, ReadPixelsTest)

