19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "CreateJavaOutputStreamAdaptor.h" 2ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkData.h" 3ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkRefCnt.h" 4ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkStream.h" 5ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "SkTypes.h" 6ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "Utils.h" 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 860126efd7d905ca24822765c6dafac17fef278abBen Wagner#include <JNIHelp.h> 960126efd7d905ca24822765c6dafac17fef278abBen Wagner#include <memory> 1060126efd7d905ca24822765c6dafac17fef278abBen Wagner 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gInputStream_readMethodID; 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gInputStream_skipMethodID; 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III/** 157315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III * Wrapper for a Java InputStream. 16ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III */ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass JavaInputStreamAdaptor : public SkStream { 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar) 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) { 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(ar); 22ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fCapacity = env->GetArrayLength(ar); 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(fCapacity > 0); 24ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fBytesRead = 0; 25ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fIsAtEnd = false; 26ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 27ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 28ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III virtual size_t read(void* buffer, size_t size) { 29ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (NULL == buffer) { 30ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (0 == size) { 31ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return 0; 32ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } else { 33ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III /* InputStream.skip(n) can return <=0 but still not be at EOF 34ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III If we see that value, we need to call read(), which will 35ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III block if waiting for more data, or return -1 at EOF 36ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III */ 37ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III size_t amountSkipped = 0; 38ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III do { 39ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III size_t amount = this->doSkip(size - amountSkipped); 40ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (0 == amount) { 41ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III char tmp; 42ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III amount = this->doRead(&tmp, 1); 43ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (0 == amount) { 44ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III // if read returned 0, we're at EOF 45ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fIsAtEnd = true; 46ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III break; 47ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 48ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 49ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III amountSkipped += amount; 50ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } while (amountSkipped < size); 51ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return amountSkipped; 52ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 53ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 54ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return this->doRead(buffer, size); 55ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 56ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 57ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III virtual bool isAtEnd() const { 58ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return fIsAtEnd; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 60dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 61ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins IIIprivate: 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t doRead(void* buffer, size_t size) { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* env = fEnv; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t bytesRead = 0; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read the bytes 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 672bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint requested = 0; 682bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat if (size > static_cast<size_t>(fCapacity)) { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requested = fCapacity; 702bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat } else { 712bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // This is safe because requested is clamped to (jint) 722bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // fCapacity. 732bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat requested = static_cast<jint>(size); 742bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat } 75dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint n = env->CallIntMethod(fJavaInputStream, 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gInputStream_readMethodID, fJavaByteArray, 0, requested); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("---- read threw an exception\n"); 8291332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III // Consider the stream to be at the end, since there was an error. 8391332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III fIsAtEnd = true; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 86dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 878cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications. 88ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III fIsAtEnd = true; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; // eof 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 91dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->GetByteArrayRegion(fJavaByteArray, 0, n, 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<jbyte*>(buffer)); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("---- read:GetByteArrayRegion threw an exception\n"); 9891332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III // The error was not with the stream itself, but consider it to be at the 9991332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III // end, since we do not have a way to recover. 10091332e7ecac06ef4cd3320095689e6af21e13dc6Leon Scroggins III fIsAtEnd = true; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 103dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer = (void*)((char*)buffer + n); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bytesRead += n; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size -= n; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fBytesRead += n; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (size != 0); 109dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bytesRead; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 112dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t doSkip(size_t size) { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* env = fEnv; 1158cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jlong skipped = env->CallLongMethod(fJavaInputStream, 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gInputStream_skipMethodID, (jlong)size); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1218cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne SkDebugf("------- skip threw an exception\n"); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (skipped < 0) { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipped = 0; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1278cd48574a755bea86243e9f9eabaee341ecf9c60Gilles Debunne 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (size_t)skipped; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 130dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* fEnv; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fJavaInputStream; // the caller owns this object 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray fJavaByteArray; // the caller owns this object 1342bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint fCapacity; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t fBytesRead; 136ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III bool fIsAtEnd; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 139c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins IIISkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, 140c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III jbyteArray storage) { 141ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return new JavaInputStreamAdaptor(env, stream, storage); 142ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III} 143ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 144c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III 14537b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins IIIstatic SkMemoryStream* adaptor_to_mem_stream(SkStream* stream) { 14637b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III SkASSERT(stream != NULL); 14737b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III size_t bufferSize = 4096; 14837b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III size_t streamLen = 0; 14937b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III size_t len; 15037b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III char* data = (char*)sk_malloc_throw(bufferSize); 15137b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III 15237b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III while ((len = stream->read(data + streamLen, 15337b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III bufferSize - streamLen)) != 0) { 15437b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III streamLen += len; 15537b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III if (streamLen == bufferSize) { 15637b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III bufferSize *= 2; 15737b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III data = (char*)sk_realloc_throw(data, bufferSize); 15837b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III } 15937b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III } 16037b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III data = (char*)sk_realloc_throw(data, streamLen); 16137b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III 16237b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III SkMemoryStream* streamMem = new SkMemoryStream(); 16337b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III streamMem->setMemoryOwned(data, streamLen); 16437b82e32324d0911aba897880c28b2fdedc3ec9aLeon Scroggins III return streamMem; 165ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III} 166ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 167c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins IIISkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, 168c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III jbyteArray storage) { 16960126efd7d905ca24822765c6dafac17fef278abBen Wagner std::unique_ptr<SkStream> adaptor(CreateJavaInputStreamAdaptor(env, stream, storage)); 170ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III if (NULL == adaptor.get()) { 171ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return NULL; 172ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III } 173ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III return adaptor_to_mem_stream(adaptor.get()); 174ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III} 175ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gOutputStream_writeMethodID; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gOutputStream_flushMethodID; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass SkJavaOutputStream : public SkWStream { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkJavaOutputStream(JNIEnv* env, jobject stream, jbyteArray storage) 184cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage), fBytesWritten(0) { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fCapacity = env->GetArrayLength(storage); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 187dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 188cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins virtual size_t bytesWritten() const { 189cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins return fBytesWritten; 190cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins } 191cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins 1922bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat virtual bool write(const void* buffer, size_t size) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* env = fEnv; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray storage = fJavaByteArray; 195dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (size > 0) { 1972bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint requested = 0; 1982bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat if (size > static_cast<size_t>(fCapacity)) { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requested = fCapacity; 2002bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat } else { 2012bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // This is safe because requested is clamped to (jint) 2022bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat // fCapacity. 2032bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat requested = static_cast<jint>(size); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetByteArrayRegion(storage, 0, requested, 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reinterpret_cast<const jbyte*>(buffer)); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("--- write:SetByteArrayElements threw an exception\n"); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 214dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fEnv->CallVoidMethod(fJavaOutputStream, gOutputStream_writeMethodID, 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project storage, 0, requested); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkDebugf("------- write threw an exception\n"); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 223dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer = (void*)((char*)buffer + requested); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size -= requested; 226cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins fBytesWritten += requested; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 230dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void flush() { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fEnv->CallVoidMethod(fJavaOutputStream, gOutputStream_flushMethodID); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 234dd66bcbf9d6ef0c50a18d9c4b1b39ce7ef7afcc4Elliott Hughes 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate: 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv* fEnv; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fJavaOutputStream; // the caller owns this object 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray fJavaByteArray; // the caller owns this object 2392bb39d7a43fdb28ecdafd65ea4b89dc05c1ad7beAshok Bhat jint fCapacity; 240cc11f15f76a62ded3e403cb2bc818c6aa5bf261cLeon Scroggins size_t fBytesWritten; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray storage) { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static bool gInited; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!gInited) { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gInited = true; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SkJavaOutputStream(env, stream, storage); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 254d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 255d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIstatic jclass findClassCheck(JNIEnv* env, const char classname[]) { 256d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jclass clazz = env->FindClass(classname); 257d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III SkASSERT(!env->ExceptionCheck()); 258d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III return clazz; 259d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III} 260d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 261d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIstatic jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz, 262d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III const char methodname[], const char type[]) { 263d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jmethodID id = env->GetMethodID(clazz, methodname, type); 264d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III SkASSERT(!env->ExceptionCheck()); 265d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III return id; 266d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III} 267d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 268d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIint register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env) { 269d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream"); 270d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I"); 271d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J"); 272d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 273d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III jclass outputStream_Clazz = findClassCheck(env, "java/io/OutputStream"); 274d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gOutputStream_writeMethodID = getMethodIDCheck(env, outputStream_Clazz, "write", "([BII)V"); 275d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III gOutputStream_flushMethodID = getMethodIDCheck(env, outputStream_Clazz, "flush", "()V"); 276d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III 277d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III return 0; 278d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III} 279