
/*
 * 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);
    fBitmap.setConfig((SkBitmap::Config) format, width, height, 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);
        }
    }
}
