ImageDirView() { SkImageRef_GlobalPool::SetRAMBudget(320 * 1024); #ifdef SPECIFIC_IMAGE fBitmaps = new SkBitmap[3]; fStrings = new SkString[3]; fBitmapCount = 3; const SkBitmap::Config configs[] = { SkBitmap::kARGB_8888_Config, SkBitmap::kRGB_565_Config, SkBitmap::kARGB_4444_Config }; for (int i = 0; i < fBitmapCount; i++) { #if 1 SkStream* stream = new SkFILEStream(SPECIFIC_IMAGE); SetImageRef(&fBitmaps[i], stream, configs[i], SPECIFIC_IMAGE); stream->unref(); #else SkImageDecoder::DecodeFile(SPECIFIC_IMAGE, &fBitmaps[i]); #endif } #else int i, N = 0; SkOSFile::Iter iter(IMAGE_DIR, IMAGE_SUFFIX); SkString name; while (iter.next(&name)) { N += 1; } fBitmaps = new SkBitmap[N]; fStrings = new SkString[N]; iter.reset(IMAGE_DIR, IMAGE_SUFFIX); for (i = 0; i < N; i++) { iter.next(&name); SkString path(IMAGE_DIR); path.append(name); SkStream* stream = new SkFILEStream(path.c_str()); SetImageRef(&fBitmaps[i], stream, SkBitmap::kNo_Config, name.c_str()); stream->unref(); fStrings[i] = name; } fBitmapCount = N; #endif fCurrIndex = 0; fDX = fDY = 0; fSaturation = SK_Scalar1; fAngle = 0; fScale = SK_Scalar1; }
static void test_peeking_front_buffered_stream(skiatest::Reporter* r, const SkStream& original, size_t bufferSize) { SkStream* dupe = original.duplicate(); REPORTER_ASSERT(r, dupe != nullptr); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize)); REPORTER_ASSERT(r, bufferedStream != nullptr); size_t peeked = 0; for (size_t i = 1; !bufferedStream->isAtEnd(); i++) { const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream, i); if (unpeekableBytes > 0) { // This could not have returned a number greater than i. REPORTER_ASSERT(r, unpeekableBytes <= i); // We have reached the end of the buffer. Verify that it was at least // bufferSize. REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize); // No more peeking is supported. break; } peeked += i; } // Test that attempting to peek beyond the length of the buffer does not prevent rewinding. bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize)); REPORTER_ASSERT(r, bufferedStream != nullptr); const size_t bytesToPeek = bufferSize + 1; SkAutoMalloc peekStorage(bytesToPeek); SkAutoMalloc readStorage(bytesToPeek); for (size_t start = 0; start <= bufferSize; start++) { // Skip to the starting point REPORTER_ASSERT(r, bufferedStream->skip(start) == start); const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek); if (0 == bytesPeeked) { // Peeking should only fail completely if we have read/skipped beyond the buffer. REPORTER_ASSERT(r, start >= bufferSize); break; } // Only read the amount that was successfully peeked. const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked); REPORTER_ASSERT(r, bytesRead == bytesPeeked); REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked)); // This should be safe to rewind. REPORTER_ASSERT(r, bufferedStream->rewind()); } }
static jobject nativeDecodeStreamScaled(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage, jobject padding, jobject options, jboolean applyScale, jfloat scale) { jobject bitmap = NULL; SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 0); if (stream) { // for now we don't allow purgeable with java inputstreams bitmap = doDecode(env, stream, padding, options, false, false, applyScale, scale); stream->unref(); } return bitmap; }
static SkStream* extract_index8_image(const SkBitmap& bitmap, const SkIRect& srcRect) { const int rowBytes = srcRect.width(); SkStream* stream = SkNEW_ARGS(SkMemoryStream, (get_uncompressed_size(bitmap, srcRect))); uint8_t* dst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes); dst += rowBytes; } return stream; }
static SkStream* extract_gray8_image(const SkBitmap& bitmap, const SkIRect& srcRect) { SkStream* stream = SkNEW_ARGS(SkMemoryStream, (get_uncompressed_size(bitmap, srcRect))); uint8_t* dst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint8_t* src = bitmap.getAddr8(0, y); for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { dst[0] = dst[1] = dst[2] = src[x]; dst += 3; } } return stream; }
static SkStream* extract_argb8888_data(const SkBitmap& bitmap, const SkIRect& srcRect, bool extractAlpha, bool* isOpaque, bool* isTransparent) { size_t streamSize = extractAlpha ? srcRect.width() * srcRect.height() : get_uncompressed_size(bitmap, srcRect); SkStream* stream = SkNEW_ARGS(SkMemoryStream, (streamSize)); uint8_t* dst = (uint8_t*)stream->getMemoryBase(); const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint32_t* src = bitmap.getAddr32(0, y); for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { SkPMColor c = src[x]; U8CPU alpha = SkGetPackedA32(c); if (extractAlpha) { *isOpaque &= alpha == SK_AlphaOPAQUE; *isTransparent &= alpha == SK_AlphaTRANSPARENT; *dst++ = alpha; } else { if (SK_AlphaTRANSPARENT == alpha) { // It is necessary to average the color component of // transparent pixels with their surrounding neighbors // since the PDF renderer may separately re-sample the // alpha and color channels when the image is not // displayed at its native resolution. Since an alpha of // zero gives no information about the color component, // the pathological case is a white image with sharp // transparency bounds - the color channel goes to black, // and the should-be-transparent pixels are rendered // as grey because of the separate soft mask and color // resizing. c = get_argb8888_neighbor_avg_color(bitmap, x, y); *dst++ = SkGetPackedR32(c); *dst++ = SkGetPackedG32(c); *dst++ = SkGetPackedB32(c); } else { SkUnPreMultiply::Scale s = scaleTable[alpha]; *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c)); *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedG32(c)); *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c)); } } } } SkASSERT(dst == streamSize + (uint8_t*)stream->getMemoryBase()); return stream; }
// Will return 0 on failure static SkFaceRec* ref_ft_face(uint32_t fontID) { SkFaceRec* rec = gFaceRecHead; while (rec) { if (rec->fFontID == fontID) { SkASSERT(rec->fFace); rec->fRefCnt += 1; return rec; } rec = rec->fNext; } SkStream* strm = SkFontHost::OpenStream(fontID); if (NULL == strm) { SkDEBUGF(("SkFontHost::OpenStream failed opening %x\n", fontID)); return 0; } // this passes ownership of strm to the rec rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); FT_Open_Args args; memset(&args, 0, sizeof(args)); const void* memoryBase = strm->getMemoryBase(); if (NULL != memoryBase) { //printf("mmap(%s)\n", keyString.c_str()); args.flags = FT_OPEN_MEMORY; args.memory_base = (const FT_Byte*)memoryBase; args.memory_size = strm->getLength(); } else { //printf("fopen(%s)\n", keyString.c_str()); args.flags = FT_OPEN_STREAM; args.stream = &rec->fFTStream; } FT_Error err = FT_Open_Face(gFTLibrary, &args, 0, &rec->fFace); if (err) { // bad filename, try the default font fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID); SkDELETE(rec); return 0; } else { SkASSERT(rec->fFace); //fprintf(stderr, "Opened font '%s'\n", filename.c_str()); rec->fNext = gFaceRecHead; gFaceRecHead = rec; rec->fRefCnt = 1; return rec; } }
static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { NPE_CHECK_RETURN_ZERO(env, istream); // what is the lifetime of the array? Can the skstream hold onto it? jbyteArray byteArray = env->NewByteArray(16*1024); SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); if (NULL == strm) { return 0; } SkMovie* moov = SkMovie::DecodeStream(strm); strm->unref(); return create_jmovie(env, moov); }
static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, // InputStream jbyteArray storage, // byte[] jobject padding, jobject options) { // BitmapFactory$Options jobject bitmap = NULL; SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 0); if (stream) { // for now we don't allow purgeable with java inputstreams bitmap = doDecode(env, stream, padding, options, false); stream->unref(); } return bitmap; }
static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz, jobject is, // InputStream jbyteArray storage, // byte[] jboolean isShareable) { jobject largeBitmap = NULL; SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024); if (stream) { // for now we don't allow shareable with java inputstreams SkMemoryStream *mStream = buildSkMemoryStream(stream); largeBitmap = doBuildTileIndex(env, mStream); stream->unref(); } return largeBitmap; }
// overrides virtual SkStream* openStream() { SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); // check for failure if (stream->getLength() <= 0) { SkDELETE(stream); // maybe MMAP isn't supported. try FILE stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); if (stream->getLength() <= 0) { SkDELETE(stream); stream = NULL; } } return stream; }
bool AutoCleanPng::decodeBounds() { if (setjmp(png_jmpbuf(fPng_ptr))) { return false; } png_set_progressive_read_fn(fPng_ptr, this, InfoCallback, nullptr, nullptr); // Arbitrary buffer size, though note that it matches (below) // SkPngCodec::processData(). FIXME: Can we better suit this to the size of // the PNG header? constexpr size_t kBufferSize = 4096; char buffer[kBufferSize]; while (true) { const size_t bytesRead = fStream->read(buffer, kBufferSize); if (!bytesRead) { // We have read to the end of the input without decoding bounds. break; } png_process_data(fPng_ptr, fInfo_ptr, (png_bytep) buffer, bytesRead); if (fDecodedBounds) { break; } } // For safety, clear the pointer to this object. png_set_progressive_read_fn(fPng_ptr, nullptr, nullptr, nullptr, nullptr); return fDecodedBounds; }
static uint8_t rbyte(SkStream& s) { uint8_t b; SkDEBUGCODE(size_t size = ) s.read(&b, 1); SkASSERT(size == 1); return b; }
static uint8_t rbyte(SkStream& s) { uint8_t b; size_t size = s.read(&b, 1); SkASSERT(size == 1); return b; }
static FPDFEMB_RESULT file_readblock(FPDFEMB_FILE_ACCESS* file, void* dst, unsigned int offset, unsigned int size) { SkStream* stream = (SkStream*)file->user; // SkDebugf("---- readblock %p %p %d %d\n", stream, dst, offset, size); if (!stream->rewind()) { SkDebugf("---- rewind failed\n"); return FPDFERR_ERROR; } if (stream->skip(offset) != offset) { SkDebugf("---- skip failed\n"); return FPDFERR_ERROR; } if (stream->read(dst, size) != size) { SkDebugf("---- read failed\n"); return FPDFERR_ERROR; } return FPDFERR_SUCCESS; }
static void test_peeking_front_buffered_stream(skiatest::Reporter* r, const SkStream& original, size_t bufferSize) { SkStream* dupe = original.duplicate(); REPORTER_ASSERT(r, dupe != NULL); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize)); REPORTER_ASSERT(r, bufferedStream != NULL); test_peeking_stream(r, bufferedStream, bufferSize); }
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) { // pass true until we know how we can share the data, and not have to // make a copy of it. SkStream* stream = new SkMemoryStream(buffer->data(), buffer->size(), true); SkTypeface* face = SkTypeface::CreateFromStream(stream); // Release the stream. stream->unref(); if (0 == face) { SkDebugf("--------- SkTypeface::CreateFromBuffer failed %d\n", buffer->size()); return NULL; } SkAutoUnref aur(face); return new FontCustomPlatformData(face); }
size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag, size_t offset, size_t length, void* data) { SkStream* stream = SkFontHost::OpenStream(fontID); if (NULL == stream) { return 0; } SkAutoUnref au(stream); SfntHeader header; if (!header.init(stream)) { return 0; } for (int i = 0; i < header.fCount; i++) { if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) { size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset); size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength); // now sanity check the caller's offset/length if (offset >= realLength) { return 0; } // if the caller is trusting the length from the file, then a // hostile file might choose a value which would overflow offset + // length. if (offset + length < offset) { return 0; } if (offset + length > realLength) { length = realLength - offset; } // skip the stream to the part of the table we want to copy from stream->rewind(); size_t bytesToSkip = realOffset + offset; if (stream->skip(bytesToSkip) != bytesToSkip) { return 0; } if (stream->read(data, length) != length) { return 0; } return length; } } return 0; }
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); // store the length of the custom font uint32_t len = fontStream->getLength(); stream->write32(len); // store the entire font in the serialized stream void* fontData = malloc(len); fontStream->read(fontData, len); stream->write(fontData, len); fontStream->unref(); free(fontData); // sk_throw(); }
static SkStream* extract_a8_alpha(const SkBitmap& bitmap, const SkIRect& srcRect, bool* isOpaque, bool* isTransparent) { const int alphaRowBytes = srcRect.width(); SkStream* stream = SkNEW_ARGS(SkMemoryStream, (alphaRowBytes * srcRect.height())); uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint8_t* src = bitmap.getAddr8(0, y); for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { alphaDst[0] = src[x]; *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE; *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT; alphaDst++; } } return stream; }
bool SkXMLParser::parse(SkStream& docStream) { ParsingContext ctx(this); if (!ctx.fXMLParser) { SkDebugf("could not create XML parser\n"); return false; } XML_SetUserData(ctx.fXMLParser, &ctx); XML_SetElementHandler(ctx.fXMLParser, start_element_handler, end_element_handler); XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler); // Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340. XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler); static const int kBufferSize = 512 SkDEBUGCODE( - 507); bool done = false; do { void* buffer = XML_GetBuffer(ctx.fXMLParser, kBufferSize); if (!buffer) { SkDebugf("could not buffer enough to continue\n"); return false; } size_t len = docStream.read(buffer, kBufferSize); done = docStream.isAtEnd(); XML_Status status = XML_ParseBuffer(ctx.fXMLParser, SkToS32(len), done); if (XML_STATUS_ERROR == status) { XML_Error error = XML_GetErrorCode(ctx.fXMLParser); int line = XML_GetCurrentLineNumber(ctx.fXMLParser); int column = XML_GetCurrentColumnNumber(ctx.fXMLParser); const XML_LChar* errorString = XML_ErrorString(error); SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, errorString); return false; } } while (!done); return true; }
static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { NPE_CHECK_RETURN_ZERO(env, istream); jbyteArray byteArray = env->NewByteArray(16*1024); ScopedLocalRef<jbyteArray> scoper(env, byteArray); SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); if (NULL == strm) { return 0; } // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. The only decoder for movies is GIF, which // will only read 6. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); SkASSERT(bufferedStream.get() != NULL); SkMovie* moov = SkMovie::DecodeStream(bufferedStream); strm->unref(); return create_jmovie(env, moov); }
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { // lookup and record if the font is custom (i.e. not a system font) bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); stream->writeBool(isCustomFont); if (isCustomFont) { SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); // store the length of the custom font uint32_t len = fontStream->getLength(); stream->write32(len); // store the entire font in the serialized stream void* fontData = malloc(len); fontStream->read(fontData, len); stream->write(fontData, len); fontStream->unref(); free(fontData); // SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len); } else { const char* name = ((FamilyTypeface*)face)->getFilePath(); // const char* name = ((FamilyTypeface*)face)->getUniqueString(); stream->write8((uint8_t)face->style()); if (NULL == name || 0 == *name) { stream->writePackedUInt(0); // SkDebugf("--- fonthost serialize null\n"); } else { uint32_t len = strlen(name); stream->writePackedUInt(len); stream->write(name, len); // SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style()); } } }
SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const { SkStream* stream = this->getLocalStream(); if (stream) { // TODO: fix issue 1176. // As of now open_stream will return a stream and unwind it, but the // SkStream is not thread safe, and if two threads use the stream they // may collide and print preview for example could still fail, // or there could be some failures in rendering if this stream is used // there. stream->rewind(); stream->ref(); // should have been provided by CreateFromStream() *ttcIndex = 0; } else { SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); if (NULL == fci.get()) { return NULL; } stream = fci->openStream(this->getIdentity()); *ttcIndex = this->getIdentity().fTTCIndex; } return stream; }
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { SkFontDescriptor descriptor; descriptor.setFamilyName(find_family_name(face)); descriptor.setStyle(face->style()); descriptor.setFontFileName(((FamilyTypeface*)face)->getUniqueString()); descriptor.serialize(stream); const bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); if (isCustomFont) { // store the entire font in the fontData SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); const uint32_t length = fontStream->getLength(); stream->writePackedUInt(length); stream->writeStream(fontStream, length); fontStream->unref(); } else { stream->writePackedUInt(0); } }
LoadState SkFontManager::checkPreData() { LoadState state = load_true; SkStream * inStream = openReadStream( SYSTEM_DL_PREDATA_FILE ); preDataHeader header = { 0, 0, 0 }; if( !inStream ) { state = load_false; goto END0; } inStream->read( &header, SYSTEM_DL_PREDATA_HEADER_LEN ); if( header.tag != __key() ) { state = load_false; goto END0; } if( getUpdateVersion() == header.updateVersion ) { state = load_true; goto END0; } else { state = load_change; goto END0; } END0: if( inStream ) SkDELETE( inStream ); return state; }
/* 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 void set(char* array[256], int index, SkStream& s, int data) { SkASSERT((unsigned)index <= 255); size_t size = rdata(s, data); if (array[index] == NULL) array[index] = (char*)sk_malloc_throw(size + 1); else { if (strlen(array[index]) < size) array[index] = (char*)sk_realloc_throw(array[index], size + 1); } s.read(array[index], size); array[index][size] = 0; }
SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const { SkStream* stream = this->getLocalStream(); if (stream) { // should have been provided by CreateFromStream() *ttcIndex = 0; SkAutoTUnref<SkStream> dupStream(stream->duplicate()); if (dupStream) { return dupStream.detach(); } // TODO: update interface use, remove the following code in this block. size_t length = stream->getLength(); const void* memory = stream->getMemoryBase(); if (NULL != memory) { return new SkMemoryStream(memory, length, true); } SkAutoTMalloc<uint8_t> allocMemory(length); stream->rewind(); if (length == stream->read(allocMemory.get(), length)) { SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream()); copyStream->setMemoryOwned(allocMemory.detach(), length); return copyStream.detach(); } stream->rewind(); stream->ref(); } else { SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); if (NULL == fci.get()) { return NULL; } stream = fci->openStream(this->getIdentity()); *ttcIndex = this->getIdentity().fTTCIndex; } return stream; }
static int Decode(GifFileType* fileType, GifByteType* out, int size) { SkStream* stream = (SkStream*) fileType->UserData; return (int) stream->read(out, size); }