125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen/*
225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * Copyright (C) 2010 The Android Open Source Project
325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen *
425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License");
525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * you may not use this file except in compliance with the License.
625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * You may obtain a copy of the License at
725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen *
825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen *      http://www.apache.org/licenses/LICENSE-2.0
925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen *
1025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software
1125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS,
1225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * See the License for the specific language governing permissions and
1425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * limitations under the License.
1525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen */
1625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
1725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#define LOG_TAG "BitmapRegionDecoder"
1825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
1925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkBitmap.h"
2025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkImageEncoder.h"
2125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "GraphicsJNI.h"
2225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkUtils.h"
2325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkTemplates.h"
2425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkPixelRef.h"
2525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkStream.h"
2625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "BitmapFactory.h"
2725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "AutoDecodeCancel.h"
2825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkBitmapRegionDecoder.h"
2925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h"
3025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "Utils.h"
3125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
3225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <android_runtime/AndroidRuntime.h>
3325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "android_util_Binder.h"
3425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "android_nio_utils.h"
3525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h"
3625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
3725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <binder/Parcel.h>
3825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <jni.h>
3925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <utils/Asset.h>
4025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <sys/stat.h>
4125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
4225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jclass gFileDescriptor_class;
4325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jfieldID gFileDescriptor_descriptor;
4425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
4525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#if 0
4625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    #define TRACE_BITMAP(code)  code
4725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#else
4825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    #define TRACE_BITMAP(code)
4925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#endif
5025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
5125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenusing namespace android;
5225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
5325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
5425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    size_t bufferSize = 4096;
5525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    size_t streamLen = 0;
5625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    size_t len;
5725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    char* data = (char*)sk_malloc_throw(bufferSize);
5825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
5925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    while ((len = stream->read(data + streamLen,
6025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                    bufferSize - streamLen)) != 0) {
6125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        streamLen += len;
6225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        if (streamLen == bufferSize) {
6325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            bufferSize *= 2;
6425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            data = (char*)sk_realloc_throw(data, bufferSize);
6525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        }
6625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
6725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    data = (char*)sk_realloc_throw(data, streamLen);
6825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
6925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkMemoryStream* streamMem = new SkMemoryStream();
7025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    streamMem->setMemoryOwned(data, streamLen);
7125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return streamMem;
7225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
7325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
7425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) {
7525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
7625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    int width, height;
7725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (NULL == decoder) {
7825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        doThrowIOE(env, "Image format not supported");
7925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        return nullObjectReturn("SkImageDecoder::Factory returned null");
8025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
8125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
8225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true);
8325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    decoder->setAllocator(javaAllocator);
8425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env);
8525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    decoder->setReporter(javaMemoryReporter);
8625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    javaAllocator->unref();
8725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    javaMemoryReporter->unref();
8825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
8925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (!decoder->buildTileIndex(stream, &width, &height)) {
9025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        char msg[100];
9125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder",
9225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                decoder->getFormatName());
9325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        doThrowIOE(env, msg);
9425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        return nullObjectReturn("decoder->buildTileIndex returned false");
9525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
9625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
9725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height);
9825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
9925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return GraphicsJNI::createBitmapRegionDecoder(env, bm);
10025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
10125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
10225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
10325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                     int offset, int length, jboolean isShareable) {
10425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    /*  If isShareable we could decide to just wrap the java array and
10525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        share it, but that means adding a globalref to the java array object
10625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        For now we just always copy the array's data if isShareable.
10725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen     */
10825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    AutoJavaByteArray ar(env, byteArray);
10925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
11025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return doBuildTileIndex(env, stream);
11125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
11225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
11325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz,
11425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                          jobject fileDescriptor, jboolean isShareable) {
11525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
11625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
11725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    jint descriptor = env->GetIntField(fileDescriptor,
11825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                       gFileDescriptor_descriptor);
11925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkStream *stream = NULL;
12025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    struct stat fdStat;
12125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    int newFD;
12225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (fstat(descriptor, &fdStat) == -1) {
12325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        doThrowIOE(env, "broken file descriptor");
12425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        return nullObjectReturn("fstat return -1");
12525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
12625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
12725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (isShareable &&
12825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            S_ISREG(fdStat.st_mode) &&
12925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            (newFD = ::dup(descriptor)) != -1) {
13025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        SkFDStream* fdStream = new SkFDStream(newFD, true);
13125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        if (!fdStream->isValid()) {
13225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            fdStream->unref();
13325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            return NULL;
13425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        }
13525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        stream = fdStream;
13625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    } else {
13725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        /* Restore our offset when we leave, so we can be called more than once
13825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen           with the same descriptor. This is only required if we didn't dup the
13925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen           file descriptor, but it is OK to do it all the time.
14025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        */
14125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        AutoFDSeek as(descriptor);
14225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
14325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        SkFDStream* fdStream = new SkFDStream(descriptor, false);
14425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        if (!fdStream->isValid()) {
14525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            fdStream->unref();
14625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            return NULL;
14725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        }
14825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        stream = buildSkMemoryStream(fdStream);
14925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        fdStream->unref();
15025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
15125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
15225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return doBuildTileIndex(env, stream);
15325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
15425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
15525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
15625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                  jobject is,       // InputStream
15725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                  jbyteArray storage, // byte[]
15825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                  jboolean isShareable) {
15925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    jobject largeBitmap = NULL;
16025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
16125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
16225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (stream) {
16325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        // for now we don't allow shareable with java inputstreams
16425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        SkMemoryStream *mStream = buildSkMemoryStream(stream);
16525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        largeBitmap = doBuildTileIndex(env, mStream);
16625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        stream->unref();
16725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
16825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return largeBitmap;
16925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
17025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
17125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
17225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                 jint native_asset, // Asset
17325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                 jboolean isShareable) {
17425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkStream* stream, *assStream;
17525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    Asset* asset = reinterpret_cast<Asset*>(native_asset);
17625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    assStream = new AssetStreamAdaptor(asset);
17725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    stream = buildSkMemoryStream(assStream);
17825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    assStream->unref();
17925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return doBuildTileIndex(env, stream);
18025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
18125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
18225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen/*
18325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * nine patch not supported
18425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen *
18525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * purgeable not supported
18625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * reportSizeToVM not supported
18725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen */
18825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd,
18925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        int start_x, int start_y, int width, int height, jobject options) {
19025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkImageDecoder *decoder = brd->getDecoder();
19125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    int sampleSize = 1;
19225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
19325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    bool doDither = true;
19425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    bool preferQualityOverSpeed = false;
19525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
19625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (NULL != options) {
19725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
19825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        // initialize these, in case we fail later on
19925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        env->SetIntField(options, gOptions_widthFieldID, -1);
20025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        env->SetIntField(options, gOptions_heightFieldID, -1);
20125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        env->SetObjectField(options, gOptions_mimeFieldID, 0);
20225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
20325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
20425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
20525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
20625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        preferQualityOverSpeed = env->GetBooleanField(options,
20725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                gOptions_preferQualityOverSpeedFieldID);
20825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
20925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
21025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    decoder->setDitherImage(doDither);
21125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
21225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkBitmap*           bitmap = new SkBitmap;
21325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkAutoTDelete<SkBitmap>       adb(bitmap);
21425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    AutoDecoderCancel   adc(options, decoder);
21525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
21625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // To fix the race condition in case "requestCancelDecode"
21725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // happens earlier than AutoDecoderCancel object is added
21825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // to the gAutoDecoderCancelMutex linked list.
21925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
22025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        return nullObjectReturn("gOptions_mCancelID");;
22125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
22225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
22325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkIRect region;
22425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    region.fLeft = start_x;
22525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    region.fTop = start_y;
22625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    region.fRight = start_x + width;
22725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    region.fBottom = start_y + height;
22825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
22925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) {
23025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        return nullObjectReturn("decoder->decodeRegion returned false");
23125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
23225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
23325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // update options (if any)
23425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    if (NULL != options) {
23525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
23625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
23725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        // TODO: set the mimeType field with the data from the codec.
23825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        // but how to reuse a set of strings, rather than allocating new one
23925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        // each time?
24025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        env->SetObjectField(options, gOptions_mimeFieldID,
24125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                            getMimeTypeString(env, decoder->getFormat()));
24225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    }
24325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
24425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // detach bitmap from its autotdeleter, since we want to own it now
24525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    adb.detach();
24625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
24725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkPixelRef* pr;
24825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    pr = bitmap->pixelRef();
24925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // promise we will never change our pixels (great for sharing and pictures)
25025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    pr->setImmutable();
25125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    // now create the java bitmap
25225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
25325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
25425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
25525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
25625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return brd->getHeight();
25725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
25825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
25925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
26025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return brd->getWidth();
26125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
26225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
26325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
26425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    delete brd;
26525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
26625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
26725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen///////////////////////////////////////////////////////////////////////////////
26825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
26925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <android_runtime/AndroidRuntime.h>
27025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
27125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic JNINativeMethod gBitmapRegionDecoderMethods[] = {
27225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeDecodeRegion",
27325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
27425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        (void*)nativeDecodeRegion},
27525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
27625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeGetHeight", "(I)I", (void*)nativeGetHeight},
27725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
27825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeGetWidth", "(I)I", (void*)nativeGetWidth},
27925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
28025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeClean", "(I)V", (void*)nativeClean},
28125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
28225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeNewInstance",
28325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        "([BIIZ)Landroid/graphics/BitmapRegionDecoder;",
28425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        (void*)nativeNewInstanceFromByteArray
28525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    },
28625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
28725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeNewInstance",
28825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;",
28925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        (void*)nativeNewInstanceFromStream
29025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    },
29125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
29225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeNewInstance",
29325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;",
29425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        (void*)nativeNewInstanceFromFileDescriptor
29525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    },
29625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
29725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    {   "nativeNewInstance",
29825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        "(IZ)Landroid/graphics/BitmapRegionDecoder;",
29925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen        (void*)nativeNewInstanceFromAsset
30025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    },
30125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen};
30225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
30325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#define kClassPathName  "android/graphics/BitmapRegionDecoder"
30425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
30525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jclass make_globalref(JNIEnv* env, const char classname[]) {
30625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    jclass c = env->FindClass(classname);
30725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkASSERT(c);
30825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return (jclass)env->NewGlobalRef(c);
30925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
31025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
31125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
31225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen                                const char fieldname[], const char type[]) {
31325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    jfieldID id = env->GetFieldID(clazz, fieldname, type);
31425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    SkASSERT(id);
31525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return id;
31625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
31725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
31825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env);
31925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env)
32025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen{
32125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen
32225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
32325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
32425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
32525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen            gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods));
32625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}
327