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

#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkSurface.h"

uint32_t SkImage::NextUniqueID() {
    static int32_t gUniqueID;

    // never return 0;
    uint32_t id;
    do {
        id = sk_atomic_inc(&gUniqueID) + 1;
    } while (0 == id);
    return id;
}

void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
    as_IB(this)->onDraw(canvas, x, y, paint);
}

void SkImage::drawRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
                   const SkPaint* paint) const {
    as_IB(this)->onDrawRect(canvas, src, dst, paint);
}

const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
    SkImageInfo infoStorage;
    size_t rowBytesStorage;
    if (NULL == info) {
        info = &infoStorage;
    }
    if (NULL == rowBytes) {
        rowBytes = &rowBytesStorage;
    }
    return as_IB(this)->onPeekPixels(info, rowBytes);
}

bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
    if (NULL == bitmap) {
        return false;
    }

    SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());

    // trim against the bitmap, if its already been allocated
    if (bitmap->pixelRef()) {
        bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
        bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
        if (bounds.isEmpty()) {
            return false;
        }
    }

    if (subset && !bounds.intersect(*subset)) {
        // perhaps we could return true + empty-bitmap?
        return false;
    }
    return as_IB(this)->onReadPixels(bitmap, bounds);
}

GrTexture* SkImage::getTexture() {
    return as_IB(this)->onGetTexture();
}

SkShader* SkImage::newShader(SkShader::TileMode tileX,
                             SkShader::TileMode tileY,
                             const SkMatrix* localMatrix) const {
    return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
}

SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
    SkBitmap bm;
    if (as_IB(this)->getROPixels(&bm)) {
        return SkImageEncoder::EncodeData(bm, type, quality);
    }
    return NULL;
}

SkSurface* SkImage::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) const {
    if (NULL == props) {
        props = &as_IB(this)->props();
    }
    return as_IB(this)->onNewSurface(info, *props);
}

///////////////////////////////////////////////////////////////////////////////

static bool raster_canvas_supports(const SkImageInfo& info) {
    switch (info.colorType()) {
        case kN32_SkColorType:
            return kUnpremul_SkAlphaType != info.alphaType();
        case kRGB_565_SkColorType:
            return true;
        case kAlpha_8_SkColorType:
            return true;
        default:
            break;
    }
    return false;
}

bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
    if (bitmap->pixelRef()) {
        const SkImageInfo info = bitmap->info();
        if (kUnknown_SkColorType == info.colorType()) {
            return false;
        }
        if (!raster_canvas_supports(info)) {
            return false;
        }
    } else {
        SkBitmap tmp;
        if (!tmp.tryAllocN32Pixels(subset.width(), subset.height())) {
            return false;
        }
        *bitmap = tmp;
    }

    SkRect srcR, dstR;
    srcR.set(subset);
    dstR = srcR;
    dstR.offset(-dstR.left(), -dstR.top());

    SkCanvas canvas(*bitmap);

    SkPaint paint;
    paint.setXfermodeMode(SkXfermode::kClear_Mode);
    canvas.drawRect(dstR, paint);

    canvas.drawImageRect(this, &srcR, dstR);
    return true;
}
