19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "CreateJavaOutputStreamAdaptor.h" 2ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "JNIHelp.h" 3ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkData.h" 4ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkRefCnt.h" 5ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkStream.h" 6ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkTypes.h" 7ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "Utils.h" 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gInputStream_readMethodID; 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gInputStream_skipMethodID; 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III/** 137315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III * Wrapper for a Java InputStream. 14ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III */ 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass JavaInputStreamAdaptor : public SkStream { 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar) 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) { 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(ar); 20ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fCapacity = env->GetArrayLength(ar); 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(fCapacity > 0); 22ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fBytesRead = 0; 23ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fIsAtEnd = false; 24ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 25ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 26ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III virtual size_t read(void* buffer, size_t size) { 27ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III JNIEnv* env = fEnv; 28ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (NULL == buffer) { 29ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (0 == size) { 30ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return 0; 31ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } else { 32ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III /* InputStream.skip(n) can return <=0 but still not be at EOF 33ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III If we see that value, we need to call read(), which will 34ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III block if waiting for more data, or return -1 at EOF 35ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III */ 36ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III size_t amountSkipped = 0; 37ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III do { 38ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III size_t amount = this->doSkip(size - amountSkipped); 39ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (0 == amount) { 40ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III char tmp; 41ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III amount = this->doRead(&tmp, 1); 42ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (0 == amount) { 43ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III // if read returned 0, we're at EOF 44ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fIsAtEnd = true; 45ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III break; 46ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 47ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 48ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III amountSkipped += amount; 49ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } while (amountSkipped < size); 50ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return amountSkipped; 51ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 52ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 53ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return this->doRead(buffer, size); 54ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 55ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 56ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III virtual bool isAtEnd() const { 57ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return fIsAtEnd; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 59dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 60ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins IIIprivate: 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t doRead(void* buffer, size_t size) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* env = fEnv; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t bytesRead = 0; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read the bytes 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 662bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint requested = 0; 672bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat if (size > static_cast<size_t>(fCapacity)) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requested = fCapacity; 692bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat } else { 702bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // This is safe because requested is clamped to (jint) 712bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // fCapacity. 722bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat requested = static_cast<jint>(size); 732bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat } 74dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint n = env->CallIntMethod(fJavaInputStream, 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gInputStream_readMethodID, fJavaByteArray, 0, requested); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("---- read threw an exception\n"); 8191332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III // Consider the stream to be at the end, since there was an error. 8291332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III fIsAtEnd = true; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 85dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 868cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications. 87ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fIsAtEnd = true; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; // eof 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 90dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->GetByteArrayRegion(fJavaByteArray, 0, n, 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<jbyte*>(buffer)); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("---- read:GetByteArrayRegion threw an exception\n"); 9791332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III // The error was not with the stream itself, but consider it to be at the 9891332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III // end, since we do not have a way to recover. 9991332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III fIsAtEnd = true; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 102dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer = (void*)((char*)buffer + n); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bytesRead += n; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size -= n; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fBytesRead += n; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (size != 0); 108dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bytesRead; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 111dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t doSkip(size_t size) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* env = fEnv; 1148cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jlong skipped = env->CallLongMethod(fJavaInputStream, 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gInputStream_skipMethodID, (jlong)size); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1208cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne SkDebugf("------- skip threw an exception\n"); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (skipped < 0) { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipped = 0; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1268cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (size_t)skipped; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 129dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* fEnv; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fJavaInputStream; // the caller owns this object 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray fJavaByteArray; // the caller owns this object 1332bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint fCapacity; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t fBytesRead; 135ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III bool fIsAtEnd; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 138c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins IIISkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, 139c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III jbyteArray storage) { 140ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return new JavaInputStreamAdaptor(env, stream, storage); 141ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III} 142ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 143c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III 14437b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins IIIstatic SkMemoryStream* adaptor_to_mem_stream(SkStream* stream) { 14537b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III SkASSERT(stream != NULL); 14637b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III size_t bufferSize = 4096; 14737b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III size_t streamLen = 0; 14837b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III size_t len; 14937b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III char* data = (char*)sk_malloc_throw(bufferSize); 15037b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III 15137b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III while ((len = stream->read(data + streamLen, 15237b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III bufferSize - streamLen)) != 0) { 15337b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III streamLen += len; 15437b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III if (streamLen == bufferSize) { 15537b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III bufferSize *= 2; 15637b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III data = (char*)sk_realloc_throw(data, bufferSize); 15737b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III } 15837b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III } 15937b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III data = (char*)sk_realloc_throw(data, streamLen); 16037b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III 16137b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III SkMemoryStream* streamMem = new SkMemoryStream(); 16237b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III streamMem->setMemoryOwned(data, streamLen); 16337b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III return streamMem; 164ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III} 165ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 166c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins IIISkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, 167c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III jbyteArray storage) { 168c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III SkAutoTUnref<SkStream> adaptor(CreateJavaInputStreamAdaptor(env, stream, storage)); 169ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (NULL == adaptor.get()) { 170ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return NULL; 171ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 172ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return adaptor_to_mem_stream(adaptor.get()); 173ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III} 174ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gOutputStream_writeMethodID; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gOutputStream_flushMethodID; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass SkJavaOutputStream : public SkWStream { 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkJavaOutputStream(JNIEnv* env, jobject stream, jbyteArray storage) 183cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage), fBytesWritten(0) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fCapacity = env->GetArrayLength(storage); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 186dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 187cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins virtual size_t bytesWritten() const { 188cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins return fBytesWritten; 189cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins } 190cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins 1912bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat virtual bool write(const void* buffer, size_t size) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* env = fEnv; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray storage = fJavaByteArray; 194dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (size > 0) { 1962bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint requested = 0; 1972bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat if (size > static_cast<size_t>(fCapacity)) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requested = fCapacity; 1992bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat } else { 2002bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // This is safe because requested is clamped to (jint) 2012bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // fCapacity. 2022bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat requested = static_cast<jint>(size); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetByteArrayRegion(storage, 0, requested, 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<const jbyte*>(buffer)); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("--- write:SetByteArrayElements threw an exception\n"); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 213dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fEnv->CallVoidMethod(fJavaOutputStream, gOutputStream_writeMethodID, 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project storage, 0, requested); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("------- write threw an exception\n"); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 222dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer = (void*)((char*)buffer + requested); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size -= requested; 225cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins fBytesWritten += requested; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 229dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void flush() { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fEnv->CallVoidMethod(fJavaOutputStream, gOutputStream_flushMethodID); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 233dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate: 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* fEnv; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fJavaOutputStream; // the caller owns this object 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray fJavaByteArray; // the caller owns this object 2382bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint fCapacity; 239cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins size_t fBytesWritten; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray storage) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static bool gInited; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!gInited) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gInited = true; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SkJavaOutputStream(env, stream, storage); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 253d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 254d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIstatic jclass findClassCheck(JNIEnv* env, const char classname[]) { 255d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jclass clazz = env->FindClass(classname); 256d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III SkASSERT(!env->ExceptionCheck()); 257d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III return clazz; 258d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III} 259d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 260d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIstatic jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz, 261d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III const char methodname[], const char type[]) { 262d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jmethodID id = env->GetMethodID(clazz, methodname, type); 263d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III SkASSERT(!env->ExceptionCheck()); 264d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III return id; 265d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III} 266d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 267d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIint register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env) { 268d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream"); 269d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I"); 270d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J"); 271d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 272d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jclass outputStream_Clazz = findClassCheck(env, "java/io/OutputStream"); 273d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gOutputStream_writeMethodID = getMethodIDCheck(env, outputStream_Clazz, "write", "([BII)V"); 274d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gOutputStream_flushMethodID = getMethodIDCheck(env, outputStream_Clazz, "flush", "()V"); 275d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 276d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III return 0; 277d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III} 278