
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "SkDrawBitmap.h"
#include "SkAnimateMaker.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkPaint.h"
#include "SkStream.h"

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkBaseBitmap::fInfo[] = {
    SK_MEMBER(x, Float),
    SK_MEMBER(y, Float)
};

#endif

DEFINE_GET_MEMBER(SkBaseBitmap);

SkBaseBitmap::SkBaseBitmap() : x(0), y(0) {
}

SkBaseBitmap::~SkBaseBitmap() {
}

bool SkBaseBitmap::draw(SkAnimateMaker& maker) {
    SkBoundableAuto boundable(this, maker);
    maker.fCanvas->drawBitmap(fBitmap, x, y, maker.fPaint);
    return false;
}

enum SkDrawBitmap_Properties {
    SK_PROPERTY(erase)
};

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkDrawBitmap::fInfo[] = {
    SK_MEMBER_INHERITED,
    SK_MEMBER_PROPERTY(erase, ARGB),
    SK_MEMBER(format, BitmapFormat),
    SK_MEMBER(height, Int),
    SK_MEMBER(rowBytes, Int),
    SK_MEMBER(width, Int),
};

#endif

DEFINE_GET_MEMBER(SkDrawBitmap);

SkDrawBitmap::SkDrawBitmap() : format((SkBitmap::Config) -1), height(-1),
    rowBytes(0),    width(-1), fColor(0), fColorSet(false) {
}

SkDrawBitmap::~SkDrawBitmap() {
}

#ifdef SK_DUMP_ENABLED
void SkDrawBitmap::dump(SkAnimateMaker* maker) {
    dumpBase(maker);
    dumpAttrs(maker);
    if (fColorSet)
        SkDebugf("erase=\"argb(%d,%d,%d,%d)\" ", SkColorGetA(fColor)/255, SkColorGetR(fColor),
            SkColorGetG(fColor), SkColorGetB(fColor));
    if (rowBytes > 0)
        SkDebugf("rowBytes=\"%d\" ", rowBytes);
    const char* formatName;
    switch (format) {
        case 0: formatName = "none"; break;
        case 1: formatName = "A8"; break;
        case 2: formatName = "Index8"; break;
        case 3: formatName = "RGB16"; break;
        case 4: formatName = "RGB32"; break;
    }
    SkDebugf("format=\"%s\" />\n", formatName);
}
#endif

void SkDrawBitmap::onEndElement(SkAnimateMaker&) {
    SkASSERT(width != -1);
    SkASSERT(height != -1);
    SkASSERT(rowBytes >= 0);
    SkColorType colorType = SkBitmapConfigToColorType((SkBitmap::Config)format);
    fBitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType), rowBytes);
    fBitmap.allocPixels();
    if (fColorSet)
        fBitmap.eraseColor(fColor);
}

bool SkDrawBitmap::setProperty(int index, SkScriptValue& value)
{
    switch (index) {
        case SK_PROPERTY(erase):
            SkASSERT(value.fType == SkType_ARGB);
            fColor = value.fOperand.fS32;
            fColorSet = true;
            break;
        default:
            SkASSERT(0);
            return false;
    }
    return true;
}


enum SkImageBaseBitmap_Properties {
    SK_PROPERTY(height),
    SK_PROPERTY(width)
};

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkImageBaseBitmap::fInfo[] = {
    SK_MEMBER_INHERITED,
    SK_MEMBER(base64, Base64),
    SK_MEMBER_PROPERTY(height, Int),
    SK_MEMBER(src, String),
    SK_MEMBER_PROPERTY(width, Int)
};

#endif

DEFINE_GET_MEMBER(SkImageBaseBitmap);

SkImageBaseBitmap::SkImageBaseBitmap() : fDirty(true), fUriBase(NULL) {
    base64.fData = NULL;
    base64.fLength = 0;
}

SkImageBaseBitmap::~SkImageBaseBitmap() {
    delete[] base64.fData;
}

SkDisplayable* SkImageBaseBitmap::deepCopy(SkAnimateMaker* maker) {
    SkDisplayable* copy = INHERITED::deepCopy(maker);
    ((SkImageBaseBitmap*) copy)->fUriBase = ((SkImageBaseBitmap*) this)->fUriBase;
    return copy;
}

void SkImageBaseBitmap::dirty() {
    fDirty = true;
}

bool SkImageBaseBitmap::draw(SkAnimateMaker& maker) {
    if (fDirty)
        resolve();
    return INHERITED::draw(maker);
}

bool SkImageBaseBitmap::getProperty(int index, SkScriptValue* value) const {
    if (fDirty)
        resolve();
    switch (index) {
        case SK_PROPERTY(height):
            value->fOperand.fS32 = fBitmap.height();
            break;
        case SK_PROPERTY(width):
            value->fOperand.fS32 = fBitmap.width();
            break;
    default:
        SkASSERT(0);
        return false;
    }
    value->fType = SkType_Int;
    return true;
}

void SkImageBaseBitmap::onEndElement(SkAnimateMaker& maker) {
    fUriBase = maker.fPrefix.c_str();
}

void SkImageBaseBitmap::resolve() {
    fDirty = false;
    if (base64.fData) {
        fBitmap.reset();
        SkImageDecoder::DecodeMemory(base64.fData, base64.fLength, &fBitmap);
    } else if (src.size()) {
        if (fLast.equals(src))
            return;
        fLast.set(src);
        fBitmap.reset();

        //SkStream* stream = SkStream::GetURIStream(fUriBase, src.c_str());
        SkAutoTUnref<SkStreamAsset> stream(SkStream::NewFromFile(src.c_str()));
        if (stream.get()) {
            SkImageDecoder::DecodeStream(stream, &fBitmap);
        }
    }
}
