michael@0: michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkBitmap.h" michael@0: #include "SkErrorInternals.h" michael@0: #include "SkReadBuffer.h" michael@0: #include "SkStream.h" michael@0: #include "SkTypeface.h" michael@0: michael@0: static uint32_t default_flags() { michael@0: uint32_t flags = 0; michael@0: #ifdef SK_SCALAR_IS_FLOAT michael@0: flags |= SkReadBuffer::kScalarIsFloat_Flag; michael@0: #endif michael@0: if (8 == sizeof(void*)) { michael@0: flags |= SkReadBuffer::kPtrIs64Bit_Flag; michael@0: } michael@0: return flags; michael@0: } michael@0: michael@0: SkReadBuffer::SkReadBuffer() { michael@0: fFlags = default_flags(); michael@0: fMemoryPtr = NULL; michael@0: michael@0: fBitmapStorage = NULL; michael@0: fTFArray = NULL; michael@0: fTFCount = 0; michael@0: michael@0: fFactoryTDArray = NULL; michael@0: fFactoryArray = NULL; michael@0: fFactoryCount = 0; michael@0: fBitmapDecoder = NULL; michael@0: #ifdef DEBUG_NON_DETERMINISTIC_ASSERT michael@0: fDecodedBitmapIndex = -1; michael@0: #endif // DEBUG_NON_DETERMINISTIC_ASSERT michael@0: } michael@0: michael@0: SkReadBuffer::SkReadBuffer(const void* data, size_t size) { michael@0: fFlags = default_flags(); michael@0: fReader.setMemory(data, size); michael@0: fMemoryPtr = NULL; michael@0: michael@0: fBitmapStorage = NULL; michael@0: fTFArray = NULL; michael@0: fTFCount = 0; michael@0: michael@0: fFactoryTDArray = NULL; michael@0: fFactoryArray = NULL; michael@0: fFactoryCount = 0; michael@0: fBitmapDecoder = NULL; michael@0: #ifdef DEBUG_NON_DETERMINISTIC_ASSERT michael@0: fDecodedBitmapIndex = -1; michael@0: #endif // DEBUG_NON_DETERMINISTIC_ASSERT michael@0: } michael@0: michael@0: SkReadBuffer::SkReadBuffer(SkStream* stream) { michael@0: fFlags = default_flags(); michael@0: const size_t length = stream->getLength(); michael@0: fMemoryPtr = sk_malloc_throw(length); michael@0: stream->read(fMemoryPtr, length); michael@0: fReader.setMemory(fMemoryPtr, length); michael@0: michael@0: fBitmapStorage = NULL; michael@0: fTFArray = NULL; michael@0: fTFCount = 0; michael@0: michael@0: fFactoryTDArray = NULL; michael@0: fFactoryArray = NULL; michael@0: fFactoryCount = 0; michael@0: fBitmapDecoder = NULL; michael@0: #ifdef DEBUG_NON_DETERMINISTIC_ASSERT michael@0: fDecodedBitmapIndex = -1; michael@0: #endif // DEBUG_NON_DETERMINISTIC_ASSERT michael@0: } michael@0: michael@0: SkReadBuffer::~SkReadBuffer() { michael@0: sk_free(fMemoryPtr); michael@0: SkSafeUnref(fBitmapStorage); michael@0: } michael@0: michael@0: bool SkReadBuffer::readBool() { michael@0: return fReader.readBool(); michael@0: } michael@0: michael@0: SkColor SkReadBuffer::readColor() { michael@0: return fReader.readInt(); michael@0: } michael@0: michael@0: SkFixed SkReadBuffer::readFixed() { michael@0: return fReader.readS32(); michael@0: } michael@0: michael@0: int32_t SkReadBuffer::readInt() { michael@0: return fReader.readInt(); michael@0: } michael@0: michael@0: SkScalar SkReadBuffer::readScalar() { michael@0: return fReader.readScalar(); michael@0: } michael@0: michael@0: uint32_t SkReadBuffer::readUInt() { michael@0: return fReader.readU32(); michael@0: } michael@0: michael@0: int32_t SkReadBuffer::read32() { michael@0: return fReader.readInt(); michael@0: } michael@0: michael@0: void SkReadBuffer::readString(SkString* string) { michael@0: size_t len; michael@0: const char* strContents = fReader.readString(&len); michael@0: string->set(strContents, len); michael@0: } michael@0: michael@0: void* SkReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) { michael@0: SkDEBUGCODE(int32_t encodingType = ) fReader.readInt(); michael@0: SkASSERT(encodingType == encoding); michael@0: *length = fReader.readInt(); michael@0: void* data = sk_malloc_throw(*length); michael@0: memcpy(data, fReader.skip(SkAlign4(*length)), *length); michael@0: return data; michael@0: } michael@0: michael@0: void SkReadBuffer::readPoint(SkPoint* point) { michael@0: point->fX = fReader.readScalar(); michael@0: point->fY = fReader.readScalar(); michael@0: } michael@0: michael@0: void SkReadBuffer::readMatrix(SkMatrix* matrix) { michael@0: fReader.readMatrix(matrix); michael@0: } michael@0: michael@0: void SkReadBuffer::readIRect(SkIRect* rect) { michael@0: memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect)); michael@0: } michael@0: michael@0: void SkReadBuffer::readRect(SkRect* rect) { michael@0: memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect)); michael@0: } michael@0: michael@0: void SkReadBuffer::readRegion(SkRegion* region) { michael@0: fReader.readRegion(region); michael@0: } michael@0: michael@0: void SkReadBuffer::readPath(SkPath* path) { michael@0: fReader.readPath(path); michael@0: } michael@0: michael@0: bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) { michael@0: const size_t count = this->getArrayCount(); michael@0: if (count == size) { michael@0: (void)fReader.skip(sizeof(uint32_t)); // Skip array count michael@0: const size_t byteLength = count * elementSize; michael@0: memcpy(value, fReader.skip(SkAlign4(byteLength)), byteLength); michael@0: return true; michael@0: } michael@0: SkASSERT(false); michael@0: fReader.skip(fReader.available()); michael@0: return false; michael@0: } michael@0: michael@0: bool SkReadBuffer::readByteArray(void* value, size_t size) { michael@0: return readArray(static_cast(value), size, sizeof(unsigned char)); michael@0: } michael@0: michael@0: bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) { michael@0: return readArray(colors, size, sizeof(SkColor)); michael@0: } michael@0: michael@0: bool SkReadBuffer::readIntArray(int32_t* values, size_t size) { michael@0: return readArray(values, size, sizeof(int32_t)); michael@0: } michael@0: michael@0: bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) { michael@0: return readArray(points, size, sizeof(SkPoint)); michael@0: } michael@0: michael@0: bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) { michael@0: return readArray(values, size, sizeof(SkScalar)); michael@0: } michael@0: michael@0: uint32_t SkReadBuffer::getArrayCount() { michael@0: return *(uint32_t*)fReader.peek(); michael@0: } michael@0: michael@0: void SkReadBuffer::readBitmap(SkBitmap* bitmap) { michael@0: const int width = this->readInt(); michael@0: const int height = this->readInt(); michael@0: // The writer stored a boolean value to determine whether an SkBitmapHeap was used during michael@0: // writing. michael@0: if (this->readBool()) { michael@0: // An SkBitmapHeap was used for writing. Read the index from the stream and find the michael@0: // corresponding SkBitmap in fBitmapStorage. michael@0: const uint32_t index = fReader.readU32(); michael@0: fReader.readU32(); // bitmap generation ID (see SkWriteBuffer::writeBitmap) michael@0: if (fBitmapStorage) { michael@0: *bitmap = *fBitmapStorage->getBitmap(index); michael@0: fBitmapStorage->releaseRef(index); michael@0: return; michael@0: } else { michael@0: // The bitmap was stored in a heap, but there is no way to access it. Set an error and michael@0: // fall through to use a place holder bitmap. michael@0: SkErrorInternals::SetError(kParseError_SkError, "SkWriteBuffer::writeBitmap " michael@0: "stored the SkBitmap in an SkBitmapHeap, but " michael@0: "SkReadBuffer has no SkBitmapHeapReader to " michael@0: "retrieve the SkBitmap."); michael@0: } michael@0: } else { michael@0: // The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap. michael@0: const size_t length = this->readUInt(); michael@0: if (length > 0) { michael@0: #ifdef DEBUG_NON_DETERMINISTIC_ASSERT michael@0: fDecodedBitmapIndex++; michael@0: #endif // DEBUG_NON_DETERMINISTIC_ASSERT michael@0: // A non-zero size means the SkBitmap was encoded. Read the data and pixel michael@0: // offset. michael@0: const void* data = this->skip(length); michael@0: const int32_t xOffset = fReader.readS32(); michael@0: const int32_t yOffset = fReader.readS32(); michael@0: if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) { michael@0: if (bitmap->width() == width && bitmap->height() == height) { michael@0: #ifdef DEBUG_NON_DETERMINISTIC_ASSERT michael@0: if (0 != xOffset || 0 != yOffset) { michael@0: SkDebugf("SkReadBuffer::readBitmap: heights match," michael@0: " but offset is not zero. \nInfo about the bitmap:" michael@0: "\n\tIndex: %d\n\tDimensions: [%d %d]\n\tEncoded" michael@0: " data size: %d\n\tOffset: (%d, %d)\n", michael@0: fDecodedBitmapIndex, width, height, length, xOffset, michael@0: yOffset); michael@0: } michael@0: #endif // DEBUG_NON_DETERMINISTIC_ASSERT michael@0: // If the width and height match, there should be no offset. michael@0: SkASSERT(0 == xOffset && 0 == yOffset); michael@0: return; michael@0: } michael@0: michael@0: // This case can only be reached if extractSubset was called, so michael@0: // the recorded width and height must be smaller than or equal to michael@0: // the encoded width and height. michael@0: // FIXME (scroggo): This assert assumes that our decoder and the michael@0: // sources encoder agree on the width and height which may not michael@0: // always be the case. Removing until it can be investigated michael@0: // further. michael@0: //SkASSERT(width <= bitmap->width() && height <= bitmap->height()); michael@0: michael@0: SkBitmap subsetBm; michael@0: SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height); michael@0: if (bitmap->extractSubset(&subsetBm, subset)) { michael@0: bitmap->swap(subsetBm); michael@0: return; michael@0: } michael@0: } michael@0: // This bitmap was encoded when written, but we are unable to decode, possibly due to michael@0: // not having a decoder. michael@0: SkErrorInternals::SetError(kParseError_SkError, michael@0: "Could not decode bitmap. Resulting bitmap will be red."); michael@0: } else { michael@0: // A size of zero means the SkBitmap was simply flattened. michael@0: bitmap->unflatten(*this); michael@0: return; michael@0: } michael@0: } michael@0: // Could not read the SkBitmap. Use a placeholder bitmap. michael@0: bitmap->allocPixels(SkImageInfo::MakeN32Premul(width, height)); michael@0: bitmap->eraseColor(SK_ColorRED); michael@0: } michael@0: michael@0: SkTypeface* SkReadBuffer::readTypeface() { michael@0: michael@0: uint32_t index = fReader.readU32(); michael@0: if (0 == index || index > (unsigned)fTFCount) { michael@0: if (index) { michael@0: SkDebugf("====== typeface index %d\n", index); michael@0: } michael@0: return NULL; michael@0: } else { michael@0: SkASSERT(fTFArray); michael@0: return fTFArray[index - 1]; michael@0: } michael@0: } michael@0: michael@0: SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) { michael@0: // michael@0: // TODO: confirm that ft matches the factory we decide to use michael@0: // michael@0: michael@0: SkFlattenable::Factory factory = NULL; michael@0: michael@0: if (fFactoryCount > 0) { michael@0: int32_t index = fReader.readU32(); michael@0: if (0 == index) { michael@0: return NULL; // writer failed to give us the flattenable michael@0: } michael@0: index -= 1; // we stored the index-base-1 michael@0: SkASSERT(index < fFactoryCount); michael@0: factory = fFactoryArray[index]; michael@0: } else if (fFactoryTDArray) { michael@0: int32_t index = fReader.readU32(); michael@0: if (0 == index) { michael@0: return NULL; // writer failed to give us the flattenable michael@0: } michael@0: index -= 1; // we stored the index-base-1 michael@0: factory = (*fFactoryTDArray)[index]; michael@0: } else { michael@0: factory = (SkFlattenable::Factory)readFunctionPtr(); michael@0: if (NULL == factory) { michael@0: return NULL; // writer failed to give us the flattenable michael@0: } michael@0: } michael@0: michael@0: // if we get here, factory may still be null, but if that is the case, the michael@0: // failure was ours, not the writer. michael@0: SkFlattenable* obj = NULL; michael@0: uint32_t sizeRecorded = fReader.readU32(); michael@0: if (factory) { michael@0: uint32_t offset = fReader.offset(); michael@0: obj = (*factory)(*this); michael@0: // check that we read the amount we expected michael@0: uint32_t sizeRead = fReader.offset() - offset; michael@0: if (sizeRecorded != sizeRead) { michael@0: // we could try to fix up the offset... michael@0: sk_throw(); michael@0: } michael@0: } else { michael@0: // we must skip the remaining data michael@0: fReader.skip(sizeRecorded); michael@0: } michael@0: return obj; michael@0: }