Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b299312 authored by Leon Scroggins III's avatar Leon Scroggins III Committed by Android (Google) Code Review
Browse files

Merge "Replace stream wrap-function w/ more specific ones" into klp-dev

parents 7be3a138 ca32021b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,7 @@
#include "GraphicsJNI.h"
#include "GraphicsJNI.h"
#include "SkDither.h"
#include "SkDither.h"
#include "SkUnPreMultiply.h"
#include "SkUnPreMultiply.h"
#include "SkStream.h"


#include <binder/Parcel.h>
#include <binder/Parcel.h>
#include "android_os_Parcel.h"
#include "android_os_Parcel.h"
+9 −46
Original line number Original line Diff line number Diff line
@@ -202,7 +202,7 @@ private:
// since we "may" create a purgeable imageref, we require the stream be ref'able
// since we "may" create a purgeable imageref, we require the stream be ref'able
// i.e. dynamically allocated, since its lifetime may exceed the current stack
// i.e. dynamically allocated, since its lifetime may exceed the current stack
// frame.
// frame.
static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding,
        jobject options, bool allowPurgeable, bool forcePurgeable = false) {
        jobject options, bool allowPurgeable, bool forcePurgeable = false) {


    int sampleSize = 1;
    int sampleSize = 1;
@@ -459,26 +459,17 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
        jobject padding, jobject options) {
        jobject padding, jobject options) {


    jobject bitmap = NULL;
    jobject bitmap = NULL;
    SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 0);
    SkAutoTUnref<SkStreamRewindable> stream(GetRewindableStream(env, is, storage));


    if (stream) {
    if (stream.get()) {
        // for now we don't allow purgeable with java inputstreams
        // for now we don't allow purgeable with java inputstreams
        // FIXME: GetRewindableStream may have made a copy, in which case
        // purgeable should be allowed.
        bitmap = doDecode(env, stream, padding, options, false, false);
        bitmap = doDecode(env, stream, padding, options, false, false);
        stream->unref();
    }
    }
    return bitmap;
    return bitmap;
}
}


static ssize_t getFDSize(int fd) {
    off64_t curr = ::lseek64(fd, 0, SEEK_CUR);
    if (curr < 0) {
        return 0;
    }
    size_t size = ::lseek(fd, 0, SEEK_END);
    ::lseek64(fd, curr, SEEK_SET);
    return size;
}

static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor,
static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor,
        jobject padding, jobject bitmapFactoryOptions) {
        jobject padding, jobject bitmapFactoryOptions) {


@@ -512,44 +503,16 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
    return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
    return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
}
}


/*  make a deep copy of the asset, and return it as a stream, or NULL if there
    was an error.
 */
static SkStream* copyAssetToStream(Asset* asset) {
    // if we could "ref/reopen" the asset, we may not need to copy it here
    off64_t size = asset->seek(0, SEEK_SET);
    if ((off64_t)-1 == size) {
        SkDebugf("---- copyAsset: asset rewind failed\n");
        return NULL;
    }

    size = asset->getLength();
    if (size <= 0) {
        SkDebugf("---- copyAsset: asset->getLength() returned %d\n", size);
        return NULL;
    }

    SkStream* stream = new SkMemoryStream(size);
    void* data = const_cast<void*>(stream->getMemoryBase());
    off64_t len = asset->read(data, size);
    if (len != size) {
        SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
        delete stream;
        stream = NULL;
    }
    return stream;
}

static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
        jobject padding, jobject options) {
        jobject padding, jobject options) {


    SkStream* stream;
    SkStreamRewindable* stream;
    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    bool forcePurgeable = optionsPurgeable(env, options);
    bool forcePurgeable = optionsPurgeable(env, options);
    if (forcePurgeable) {
    if (forcePurgeable) {
        // if we could "ref/reopen" the asset, we may not need to copy it here
        // if we could "ref/reopen" the asset, we may not need to copy it here
        // and we could assume optionsShareable, since assets are always RO
        // and we could assume optionsShareable, since assets are always RO
        stream = copyAssetToStream(asset);
        stream = CopyAssetToStream(asset);
        if (stream == NULL) {
        if (stream == NULL) {
            return NULL;
            return NULL;
        }
        }
@@ -559,7 +522,7 @@ static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
        stream = new AssetStreamAdaptor(asset);
        stream = new AssetStreamAdaptor(asset);
    }
    }
    SkAutoUnref aur(stream);
    SkAutoUnref aur(stream);
    return doDecode(env, stream, padding, options, true, forcePurgeable);
    return doDecode(env, stream, padding, options, forcePurgeable, forcePurgeable);
}
}


static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
@@ -572,7 +535,7 @@ static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
     */
     */
    bool purgeable = optionsPurgeable(env, options) && !optionsJustBounds(env, options);
    bool purgeable = optionsPurgeable(env, options) && !optionsJustBounds(env, options);
    AutoJavaByteArray ar(env, byteArray);
    AutoJavaByteArray ar(env, byteArray);
    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
    SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
    SkAutoUnref aur(stream);
    SkAutoUnref aur(stream);
    return doDecode(env, stream, NULL, options, purgeable);
    return doDecode(env, stream, NULL, options, purgeable);
}
}
+10 −33
Original line number Original line Diff line number Diff line
@@ -76,27 +76,6 @@ private:
    int fHeight;
    int fHeight;
};
};


static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
    size_t bufferSize = 4096;
    size_t streamLen = 0;
    size_t len;
    char* data = (char*)sk_malloc_throw(bufferSize);

    while ((len = stream->read(data + streamLen,
                    bufferSize - streamLen)) != 0) {
        streamLen += len;
        if (streamLen == bufferSize) {
            bufferSize *= 2;
            data = (char*)sk_realloc_throw(data, bufferSize);
        }
    }
    data = (char*)sk_realloc_throw(data, streamLen);

    SkMemoryStream* streamMem = new SkMemoryStream();
    streamMem->setMemoryOwned(data, streamLen);
    return streamMem;
}

static jobject createBitmapRegionDecoder(JNIEnv* env, SkStream* stream) {
static jobject createBitmapRegionDecoder(JNIEnv* env, SkStream* stream) {
    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
    int width, height;
    int width, height;
@@ -161,14 +140,12 @@ static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
                                  jbyteArray storage, // byte[]
                                  jbyteArray storage, // byte[]
                                  jboolean isShareable) {
                                  jboolean isShareable) {
    jobject brd = NULL;
    jobject brd = NULL;
    SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
    // for now we don't allow shareable with java inputstreams
    SkStream* stream = CopyJavaInputStream(env, is, storage);


    if (stream) {
    if (stream) {
        // for now we don't allow shareable with java inputstreams
        brd = createBitmapRegionDecoder(env, stream);
        SkMemoryStream* mStream = buildSkMemoryStream(stream);
        stream->unref(); // the decoder now holds a reference
        brd = createBitmapRegionDecoder(env, mStream);
        SkSafeUnref(mStream); // the decoder now holds a reference
        stream->unref();
    }
    }
    return brd;
    return brd;
}
}
@@ -176,14 +153,14 @@ static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
                                 jint native_asset, // Asset
                                 jint native_asset, // Asset
                                 jboolean isShareable) {
                                 jboolean isShareable) {
    SkStream* stream, *assStream;
    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    assStream = new AssetStreamAdaptor(asset);
    SkAutoTUnref<SkMemoryStream> stream(CopyAssetToStream(asset));
    stream = buildSkMemoryStream(assStream);
    if (NULL == stream.get()) {
    assStream->unref();
        return NULL;
    }


    jobject brd = createBitmapRegionDecoder(env, stream);
    jobject brd = createBitmapRegionDecoder(env, stream.get());
    SkSafeUnref(stream); // the decoder now holds a reference
    // The decoder now holds a reference to stream.
    return brd;
    return brd;
}
}


+221 −55
Original line number Original line Diff line number Diff line
#include "CreateJavaOutputStreamAdaptor.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include "JNIHelp.h"
#include "SkData.h"
#include "SkRefCnt.h"
#include "SkStream.h"
#include "SkTypes.h"
#include "Utils.h"
#include <androidfw/Asset.h>


#define RETURN_NULL_IF_NULL(value) \
#define RETURN_NULL_IF_NULL(value) \
    do { if (!(value)) { SkASSERT(0); return NULL; } } while (false)
    do { if (!(value)) { SkASSERT(0); return NULL; } } while (false)


#define RETURN_ZERO_IF_NULL(value) \
    do { if (!(value)) { SkASSERT(0); return 0; } } while (false)

static jmethodID    gInputStream_resetMethodID;
static jmethodID    gInputStream_resetMethodID;
static jmethodID    gInputStream_markMethodID;
static jmethodID    gInputStream_markMethodID;
static jmethodID    gInputStream_availableMethodID;
static jmethodID    gInputStream_markSupportedMethodID;
static jmethodID    gInputStream_readMethodID;
static jmethodID    gInputStream_readMethodID;
static jmethodID    gInputStream_skipMethodID;
static jmethodID    gInputStream_skipMethodID;


class RewindableJavaStream;

/**
 *  Non-rewindable wrapper for a Java InputStream.
 */
class JavaInputStreamAdaptor : public SkStream {
class JavaInputStreamAdaptor : public SkStream {
public:
public:
    JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar)
    JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar)
@@ -17,12 +32,52 @@ public:
        fCapacity = env->GetArrayLength(ar);
        fCapacity = env->GetArrayLength(ar);
        SkASSERT(fCapacity > 0);
        SkASSERT(fCapacity > 0);
        fBytesRead = 0;
        fBytesRead = 0;
        fIsAtEnd = false;
    }
    }


	virtual bool rewind() {
    virtual size_t read(void* buffer, size_t size) {
        JNIEnv* env = fEnv;
        if (NULL == buffer) {
            if (0 == size) {
                return 0;
            } else {
                /*  InputStream.skip(n) can return <=0 but still not be at EOF
                    If we see that value, we need to call read(), which will
                    block if waiting for more data, or return -1 at EOF
                 */
                size_t amountSkipped = 0;
                do {
                    size_t amount = this->doSkip(size - amountSkipped);
                    if (0 == amount) {
                        char tmp;
                        amount = this->doRead(&tmp, 1);
                        if (0 == amount) {
                            // if read returned 0, we're at EOF
                            fIsAtEnd = true;
                            break;
                        }
                    }
                    amountSkipped += amount;
                } while (amountSkipped < size);
                return amountSkipped;
            }
        }
        return this->doRead(buffer, size);
    }

    virtual bool isAtEnd() const {
        return fIsAtEnd;
    }

private:
    // Does not override rewind, since a JavaInputStreamAdaptor's interface
    // does not support rewinding. RewindableJavaStream, which is a friend,
    // will be able to call this method to rewind.
    bool doRewind() {
        JNIEnv* env = fEnv;
        JNIEnv* env = fEnv;


        fBytesRead = 0;
        fBytesRead = 0;
        fIsAtEnd = false;


        env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID);
        env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID);
        if (env->ExceptionCheck()) {
        if (env->ExceptionCheck()) {
@@ -53,6 +108,7 @@ public:
            }
            }


            if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications.
            if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications.
                fIsAtEnd = true;
                break;  // eof
                break;  // eof
            }
            }


@@ -92,58 +148,19 @@ public:
        return (size_t)skipped;
        return (size_t)skipped;
    }
    }


    size_t doSize() {
        JNIEnv* env = fEnv;
        jint avail = env->CallIntMethod(fJavaInputStream,
                                        gInputStream_availableMethodID);
        if (env->ExceptionCheck()) {
            env->ExceptionDescribe();
            env->ExceptionClear();
            SkDebugf("------- available threw an exception\n");
            avail = 0;
        }
        return avail;
    }

	virtual size_t read(void* buffer, size_t size) {
        JNIEnv* env = fEnv;
        if (NULL == buffer) {
            if (0 == size) {
                return this->doSize();
            } else {
                /*  InputStream.skip(n) can return <=0 but still not be at EOF
                    If we see that value, we need to call read(), which will
                    block if waiting for more data, or return -1 at EOF
                 */
                size_t amountSkipped = 0;
                do {
                    size_t amount = this->doSkip(size - amountSkipped);
                    if (0 == amount) {
                        char tmp;
                        amount = this->doRead(&tmp, 1);
                        if (0 == amount) {
                            // if read returned 0, we're at EOF
                            break;
                        }
                    }
                    amountSkipped += amount;
                } while (amountSkipped < size);
                return amountSkipped;
            }
        }
        return this->doRead(buffer, size);
    }

private:
    JNIEnv*     fEnv;
    JNIEnv*     fEnv;
    jobject     fJavaInputStream;   // the caller owns this object
    jobject     fJavaInputStream;   // the caller owns this object
    jbyteArray  fJavaByteArray;     // the caller owns this object
    jbyteArray  fJavaByteArray;     // the caller owns this object
    size_t      fCapacity;
    size_t      fCapacity;
    size_t      fBytesRead;
    size_t      fBytesRead;
    bool        fIsAtEnd;

    // Allows access to doRewind and fBytesRead.
    friend class RewindableJavaStream;
};
};


SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
SkStream* WrapJavaInputStream(JNIEnv* env, jobject stream,
                                       jbyteArray storage, int markSize) {
                              jbyteArray storage) {
    static bool gInited;
    static bool gInited;


    if (!gInited) {
    if (!gInited) {
@@ -154,8 +171,8 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
                                                           "reset", "()V");
                                                           "reset", "()V");
        gInputStream_markMethodID       = env->GetMethodID(inputStream_Clazz,
        gInputStream_markMethodID       = env->GetMethodID(inputStream_Clazz,
                                                           "mark", "(I)V");
                                                           "mark", "(I)V");
        gInputStream_availableMethodID  = env->GetMethodID(inputStream_Clazz,
        gInputStream_markSupportedMethodID = env->GetMethodID(inputStream_Clazz,
                                                           "available", "()I");
                                                              "markSupported", "()Z");
        gInputStream_readMethodID       = env->GetMethodID(inputStream_Clazz,
        gInputStream_readMethodID       = env->GetMethodID(inputStream_Clazz,
                                                           "read", "([BII)I");
                                                           "read", "([BII)I");
        gInputStream_skipMethodID       = env->GetMethodID(inputStream_Clazz,
        gInputStream_skipMethodID       = env->GetMethodID(inputStream_Clazz,
@@ -163,18 +180,167 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,


        RETURN_NULL_IF_NULL(gInputStream_resetMethodID);
        RETURN_NULL_IF_NULL(gInputStream_resetMethodID);
        RETURN_NULL_IF_NULL(gInputStream_markMethodID);
        RETURN_NULL_IF_NULL(gInputStream_markMethodID);
        RETURN_NULL_IF_NULL(gInputStream_availableMethodID);
        RETURN_NULL_IF_NULL(gInputStream_markSupportedMethodID);
        RETURN_NULL_IF_NULL(gInputStream_readMethodID);
        RETURN_NULL_IF_NULL(gInputStream_readMethodID);
        RETURN_NULL_IF_NULL(gInputStream_skipMethodID);
        RETURN_NULL_IF_NULL(gInputStream_skipMethodID);


        gInited = true;
        gInited = true;
    }
    }


    if (markSize) {
    return new JavaInputStreamAdaptor(env, stream, storage);
        env->CallVoidMethod(stream, gInputStream_markMethodID, markSize);
}
}


    return new JavaInputStreamAdaptor(env, stream, storage);
static SkMemoryStream* adaptor_to_mem_stream(SkStream* adaptor) {
    SkASSERT(adaptor != NULL);
    SkDynamicMemoryWStream wStream;
    const int bufferSize = 256 * 1024; // 256 KB, same as ViewStateSerializer.
    uint8_t buffer[bufferSize];
    do {
        size_t bytesRead = adaptor->read(buffer, bufferSize);
        wStream.write(buffer, bytesRead);
    } while (!adaptor->isAtEnd());
    SkAutoTUnref<SkData> data(wStream.copyToData());
    return new SkMemoryStream(data.get());
}

SkMemoryStream* CopyJavaInputStream(JNIEnv* env, jobject stream,
                                    jbyteArray storage) {
    SkAutoTUnref<SkStream> adaptor(WrapJavaInputStream(env, stream, storage));
    if (NULL == adaptor.get()) {
        return NULL;
    }
    return adaptor_to_mem_stream(adaptor.get());
}

/**
 *  Wrapper for a Java InputStream which is rewindable and
 *  has a length.
 */
class RewindableJavaStream : public SkStreamRewindable {
public:
    // RewindableJavaStream takes ownership of adaptor.
    RewindableJavaStream(JavaInputStreamAdaptor* adaptor, size_t length)
        : fAdaptor(adaptor)
        , fLength(length) {
        SkASSERT(fAdaptor != NULL);
    }

    virtual ~RewindableJavaStream() {
        fAdaptor->unref();
    }

    virtual bool rewind() {
        return fAdaptor->doRewind();
    }

    virtual size_t read(void* buffer, size_t size) {
        return fAdaptor->read(buffer, size);
    }

    virtual bool isAtEnd() const {
        return fAdaptor->isAtEnd();
    }

    virtual size_t getLength() const {
        return fLength;
    }

    virtual bool hasLength() const {
        return true;
    }

    virtual SkStreamRewindable* duplicate() const {
        // Duplicating this stream requires rewinding and
        // reading, which modify this Stream (and could
        // fail, leaving this one invalid).
        SkASSERT(false);
        return NULL;
    }

private:
    JavaInputStreamAdaptor* fAdaptor;
    const size_t            fLength;
};

/**
 *  If jstream is a ByteArrayInputStream, return its remaining length. Otherwise
 *  return 0.
 */
static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) {
    static jclass byteArrayInputStream_Clazz;
    static jfieldID countField;
    static jfieldID posField;

    byteArrayInputStream_Clazz = env->FindClass("java/io/ByteArrayInputStream");
    RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);

    countField = env->GetFieldID(byteArrayInputStream_Clazz, "count", "I");
    RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
    posField = env->GetFieldID(byteArrayInputStream_Clazz, "pos", "I");
    RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);

    if (env->IsInstanceOf(jstream, byteArrayInputStream_Clazz)) {
        // Return the remaining length, to keep the same behavior of using the rest of the
        // stream.
        return env->GetIntField(jstream, countField) - env->GetIntField(jstream, posField);
    }
    return 0;
}

/**
 *  If jstream is a class that has a length, return it. Otherwise
 *  return 0.
 *  Only checks for a set of subclasses.
 */
static size_t get_length_if_supported(JNIEnv* env, jobject jstream) {
    size_t len = get_length_from_byte_array_stream(env, jstream);
    if (len > 0) {
        return len;
    }
    return 0;
}

SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
                                        jbyteArray storage) {
    SkAutoTUnref<SkStream> adaptor(WrapJavaInputStream(env, stream, storage));
    if (NULL == adaptor.get()) {
        return NULL;
    }

    const size_t length = get_length_if_supported(env, stream);
    if (length > 0 && env->CallBooleanMethod(stream, gInputStream_markSupportedMethodID)) {
        // Set the readLimit for mark to the end of the stream, so it can
        // be rewound regardless of how much has been read.
        env->CallVoidMethod(stream, gInputStream_markMethodID, length);
        // RewindableJavaStream will unref adaptor when it is destroyed.
        return new RewindableJavaStream(static_cast<JavaInputStreamAdaptor*>(adaptor.detach()),
                                        length);
    }

    return adaptor_to_mem_stream(adaptor.get());
}

android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) {
    static jclass assetInputStream_Clazz;
    static jmethodID getAssetIntMethodID;

    assetInputStream_Clazz = env->FindClass("android/content/res/AssetManager$AssetInputStream");
    RETURN_NULL_IF_NULL(assetInputStream_Clazz);

    getAssetIntMethodID = env->GetMethodID(assetInputStream_Clazz, "getAssetInt", "()I");
    RETURN_NULL_IF_NULL(getAssetIntMethodID);

    if (!env->IsInstanceOf(jstream, assetInputStream_Clazz)) {
        return NULL;
    }

    jint jasset = env->CallIntMethod(jstream, getAssetIntMethodID);
    android::Asset* a = reinterpret_cast<android::Asset*>(jasset);
    if (NULL == a) {
        jniThrowNullPointerException(env, "NULL native asset");
        return NULL;
    }
    return new android::AssetStreamAdaptor(a);
}
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+63 −3
Original line number Original line Diff line number Diff line
@@ -3,10 +3,70 @@


//#include <android_runtime/AndroidRuntime.h>
//#include <android_runtime/AndroidRuntime.h>
#include "jni.h"
#include "jni.h"
#include "SkStream.h"


SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
namespace android {
                                       jbyteArray storage, int markSize = 0);
    class AssetStreamAdaptor;
}

class SkMemoryStream;
class SkStream;
class SkStreamRewindable;
class SkWStream;

/**
 *  Return an adaptor from a Java InputStream to an SkStream.
 *  @param env JNIEnv object.
 *  @param stream Pointer to Java InputStream.
 *  @param storage Java byte array for retrieving data from the
 *      Java InputStream.
 *  @return SkStream Simple subclass of SkStream which supports its
 *      basic methods like reading. Only valid until the calling
 *      function returns, since the Java InputStream is not managed
 *      by the SkStream.
 */
SkStream* WrapJavaInputStream(JNIEnv* env, jobject stream,
                              jbyteArray storage);

/**
 *  Copy a Java InputStream.
 *  @param env JNIEnv object.
 *  @param stream Pointer to Java InputStream.
 *  @param storage Java byte array for retrieving data from the
 *      Java InputStream.
 *  @return SkMemoryStream The data in stream will be copied to a new
 *      SkMemoryStream.
 *  FIXME: Could return a more generic return type if ViewStateSerializer
 *  did not require an SkMemoryStream.
 */
SkMemoryStream* CopyJavaInputStream(JNIEnv* env, jobject stream,
                                    jbyteArray storage);

/**
 *  Get a rewindable stream from a Java InputStream.
 *  @param env JNIEnv object.
 *  @param stream Pointer to Java InputStream.
 *  @param storage Java byte array for retrieving data from the
 *      Java InputStream.
 *  @return SkStreamRewindable Either a wrapper around the Java
 *      InputStream, if possible, or a copy which is rewindable.
 *      Since it may be a wrapper, must not be used after the
 *      caller returns, like the result of WrapJavaInputStream.
 */
SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
                                        jbyteArray storage);

/**
 *  If the Java InputStream is an AssetInputStream, return an adaptor.
 *  This should not be used after the calling function returns, since
 *  the caller may close the asset. Returns NULL if the stream is
 *  not an AssetInputStream.
 *  @param env JNIEnv object.
 *  @param stream Pointer to Java InputStream.
 *  @return AssetStreamAdaptor representing the InputStream, or NULL.
 *      Must not be held onto.
 */
android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject stream);

SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
                                         jbyteArray storage);
                                         jbyteArray storage);


Loading