/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "config.h"

#include "NinePatchPeeker.h"
#include "RenderSkinNinePatch.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkNinePatch.h"
#include "SkRect.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include <androidfw/Asset.h>
#include <androidfw/AssetManager.h>
#include <androidfw/ResourceTypes.h>
#include <utils/Log.h>

class SkPaint;
class SkRegion;

using namespace android;

extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
        const SkBitmap& bitmap, const Res_png_9patch& chunk,
        const SkPaint* paint, SkRegion** outRegion);

bool RenderSkinNinePatch::decodeAsset(AssetManager* am, const char* filename, NinePatch* ninepatch) {
    Asset* asset = am->open(filename, android::Asset::ACCESS_BUFFER);
    if (!asset) {
        asset = am->openNonAsset(filename, android::Asset::ACCESS_BUFFER);
        if (!asset) {
            return false;
        }
    }

    SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
    SkMemoryStream stream(asset->getBuffer(false), asset->getLength());
    SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
    if (!decoder) {
        asset->close();
        ALOGE("RenderSkinNinePatch::Failed to create an image decoder");
        return false;
    }

    decoder->setSampleSize(1);
    decoder->setDitherImage(true);
    decoder->setPreferQualityOverSpeed(false);

    NinePatchPeeker peeker(decoder);

    SkAutoTDelete<SkImageDecoder> add(decoder);

    decoder->setPeeker(&peeker);
    if (!decoder->decode(&stream, &ninepatch->m_bitmap, prefConfig, mode, true)) {
        asset->close();
        ALOGE("RenderSkinNinePatch::Failed to decode nine patch asset");
        return false;
    }

    asset->close();
    if (!peeker.fPatch) {
        ALOGE("RenderSkinNinePatch::Patch data not valid");
        return false;
    }
    void** data = &ninepatch->m_serializedPatchData;
    *data = malloc(peeker.fPatch->serializedSize());
    peeker.fPatch->serialize(*data);
    return true;
}

void RenderSkinNinePatch::DrawNinePatch(SkCanvas* canvas, const SkRect& bounds,
                                        const NinePatch& patch) {
    Res_png_9patch* data = Res_png_9patch::deserialize(patch.m_serializedPatchData);

    // if the NinePatch is bigger than the destination on a given axis the default
    // decoder will not stretch properly, therefore we fall back to skia's decoder
    // which if needed will down-sample and draw the bitmap as best as possible.
    if (patch.m_bitmap.width() >= bounds.width() || patch.m_bitmap.height() >= bounds.height()) {

        SkPaint defaultPaint;
        // matches default dither in NinePatchDrawable.java.
        defaultPaint.setDither(true);
        SkNinePatch::DrawMesh(canvas, bounds, patch.m_bitmap,
                              data->xDivs, data->numXDivs,
                              data->yDivs, data->numYDivs,
                              &defaultPaint);
    } else {
        NinePatch_Draw(canvas, bounds, patch.m_bitmap, *data, 0, 0);
    }
}
