Add a detachAsStream to SkDynamicMemoryWStream.
R=reed@google.com Review URL: https://codereview.chromium.org/19677002 git-svn-id: http://skia.googlecode.com/svn/trunk@10171 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
b835652599
commit
eacb54e174
@ -410,11 +410,9 @@ public:
|
|||||||
gm_fprintf(stdout, "(results marked with [*] will cause nonzero return value)\n");
|
gm_fprintf(stdout, "(results marked with [*] will cause nonzero return value)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool write_document(const SkString& path,
|
static bool write_document(const SkString& path, SkStreamAsset* asset) {
|
||||||
const SkDynamicMemoryWStream& document) {
|
|
||||||
SkFILEWStream stream(path.c_str());
|
SkFILEWStream stream(path.c_str());
|
||||||
SkAutoDataUnref data(document.copyToData());
|
return stream.writeStream(asset, asset->getLength());
|
||||||
return stream.write(data->data(), data->size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -665,7 +663,7 @@ public:
|
|||||||
const char renderModeDescriptor [],
|
const char renderModeDescriptor [],
|
||||||
const char *shortName,
|
const char *shortName,
|
||||||
const BitmapAndDigest* bitmapAndDigest,
|
const BitmapAndDigest* bitmapAndDigest,
|
||||||
SkDynamicMemoryWStream* document) {
|
SkStreamAsset* document) {
|
||||||
SkString path;
|
SkString path;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (gRec.fBackend == kRaster_Backend ||
|
if (gRec.fBackend == kRaster_Backend ||
|
||||||
@ -679,12 +677,12 @@ public:
|
|||||||
if (kPDF_Backend == gRec.fBackend) {
|
if (kPDF_Backend == gRec.fBackend) {
|
||||||
path = make_filename(writePath, shortName, gRec.fName, renderModeDescriptor,
|
path = make_filename(writePath, shortName, gRec.fName, renderModeDescriptor,
|
||||||
"pdf");
|
"pdf");
|
||||||
success = write_document(path, *document);
|
success = write_document(path, document);
|
||||||
}
|
}
|
||||||
if (kXPS_Backend == gRec.fBackend) {
|
if (kXPS_Backend == gRec.fBackend) {
|
||||||
path = make_filename(writePath, shortName, gRec.fName, renderModeDescriptor,
|
path = make_filename(writePath, shortName, gRec.fName, renderModeDescriptor,
|
||||||
"xps");
|
"xps");
|
||||||
success = write_document(path, *document);
|
success = write_document(path, document);
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
return kEmpty_ErrorCombination;
|
return kEmpty_ErrorCombination;
|
||||||
@ -911,7 +909,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
ErrorCombination compare_test_results_to_stored_expectations(
|
ErrorCombination compare_test_results_to_stored_expectations(
|
||||||
GM* gm, const ConfigData& gRec, const char writePath[],
|
GM* gm, const ConfigData& gRec, const char writePath[],
|
||||||
const BitmapAndDigest* actualBitmapAndDigest, SkDynamicMemoryWStream* document) {
|
const BitmapAndDigest* actualBitmapAndDigest, SkStreamAsset* document) {
|
||||||
|
|
||||||
SkString shortNamePlusConfig = make_shortname_plus_config(gm->shortName(), gRec.fName);
|
SkString shortNamePlusConfig = make_shortname_plus_config(gm->shortName(), gRec.fName);
|
||||||
SkString nameWithExtension(shortNamePlusConfig);
|
SkString nameWithExtension(shortNamePlusConfig);
|
||||||
@ -1025,24 +1023,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SkPicture* stream_to_new_picture(const SkPicture& src) {
|
static SkPicture* stream_to_new_picture(const SkPicture& src) {
|
||||||
|
|
||||||
// To do in-memory commiunications with a stream, we need to:
|
|
||||||
// * create a dynamic memory stream
|
|
||||||
// * copy it into a buffer
|
|
||||||
// * create a read stream from it
|
|
||||||
// ?!?!
|
|
||||||
|
|
||||||
SkDynamicMemoryWStream storage;
|
SkDynamicMemoryWStream storage;
|
||||||
src.serialize(&storage);
|
src.serialize(&storage);
|
||||||
|
SkAutoTUnref<SkStreamAsset> pictReadback(storage.detatchAsStream());
|
||||||
size_t streamSize = storage.getOffset();
|
SkPicture* retval = SkPicture::CreateFromStream(pictReadback);
|
||||||
SkAutoMalloc dstStorage(streamSize);
|
|
||||||
void* dst = dstStorage.get();
|
|
||||||
//char* dst = new char [streamSize];
|
|
||||||
//@todo thudson 22 April 2011 when can we safely delete [] dst?
|
|
||||||
storage.copyTo(dst);
|
|
||||||
SkMemoryStream pictReadback(dst, streamSize);
|
|
||||||
SkPicture* retval = SkPicture::CreateFromStream(&pictReadback);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1079,13 +1063,14 @@ public:
|
|||||||
bitmap = NULL; // we don't generate a bitmap rendering of the XPS file
|
bitmap = NULL; // we don't generate a bitmap rendering of the XPS file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStreamAsset> documentStream(document.detatchAsStream());
|
||||||
if (NULL == bitmap) {
|
if (NULL == bitmap) {
|
||||||
return compare_test_results_to_stored_expectations(
|
return compare_test_results_to_stored_expectations(
|
||||||
gm, gRec, writePath, NULL, &document);
|
gm, gRec, writePath, NULL, documentStream);
|
||||||
} else {
|
} else {
|
||||||
BitmapAndDigest bitmapAndDigest(*bitmap);
|
BitmapAndDigest bitmapAndDigest(*bitmap);
|
||||||
return compare_test_results_to_stored_expectations(
|
return compare_test_results_to_stored_expectations(
|
||||||
gm, gRec, writePath, &bitmapAndDigest, &document);
|
gm, gRec, writePath, &bitmapAndDigest, documentStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,8 +1078,6 @@ public:
|
|||||||
const ConfigData& gRec,
|
const ConfigData& gRec,
|
||||||
const SkBitmap& referenceBitmap,
|
const SkBitmap& referenceBitmap,
|
||||||
GrSurface* gpuTarget) {
|
GrSurface* gpuTarget) {
|
||||||
SkDynamicMemoryWStream document;
|
|
||||||
|
|
||||||
if (gRec.fBackend == kRaster_Backend ||
|
if (gRec.fBackend == kRaster_Backend ||
|
||||||
gRec.fBackend == kGPU_Backend) {
|
gRec.fBackend == kGPU_Backend) {
|
||||||
const char renderModeDescriptor[] = "-deferred";
|
const char renderModeDescriptor[] = "-deferred";
|
||||||
|
@ -280,7 +280,7 @@ public:
|
|||||||
|
|
||||||
virtual size_t getLength() const SK_OVERRIDE;
|
virtual size_t getLength() const SK_OVERRIDE;
|
||||||
|
|
||||||
const void* getMemoryBase() SK_OVERRIDE;
|
virtual const void* getMemoryBase() SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkFILE* fFILE;
|
SkFILE* fFILE;
|
||||||
@ -423,7 +423,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
SkData* copyToData() const;
|
SkData* copyToData() const;
|
||||||
|
|
||||||
// reset the stream to its original state
|
/** Reset, returning a reader stream with the current content. */
|
||||||
|
SkStreamAsset* detatchAsStream();
|
||||||
|
|
||||||
|
/** Reset the stream to its original, empty, state. */
|
||||||
void reset();
|
void reset();
|
||||||
void padToAlign4();
|
void padToAlign4();
|
||||||
private:
|
private:
|
||||||
@ -435,6 +438,10 @@ private:
|
|||||||
|
|
||||||
void invalidateCopy();
|
void invalidateCopy();
|
||||||
|
|
||||||
|
// For access to the Block type.
|
||||||
|
friend class SkBlockMemoryStream;
|
||||||
|
friend class SkBlockMemoryRefCnt;
|
||||||
|
|
||||||
typedef SkWStream INHERITED;
|
typedef SkWStream INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -661,6 +661,138 @@ void SkDynamicMemoryWStream::invalidateCopy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SkBlockMemoryRefCnt : public SkRefCnt {
|
||||||
|
public:
|
||||||
|
explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
|
||||||
|
|
||||||
|
virtual ~SkBlockMemoryRefCnt() {
|
||||||
|
SkDynamicMemoryWStream::Block* block = fHead;
|
||||||
|
while (block != NULL) {
|
||||||
|
SkDynamicMemoryWStream::Block* next = block->fNext;
|
||||||
|
sk_free(block);
|
||||||
|
block = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkDynamicMemoryWStream::Block* const fHead;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkBlockMemoryStream : public SkStreamAsset {
|
||||||
|
public:
|
||||||
|
SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
|
||||||
|
: fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
|
||||||
|
, fSize(size) , fOffset(0), fCurrentOffset(0) { }
|
||||||
|
|
||||||
|
SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
|
||||||
|
: fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
|
||||||
|
, fSize(size) , fOffset(0), fCurrentOffset(0) { }
|
||||||
|
|
||||||
|
virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
|
||||||
|
size_t count = rawCount;
|
||||||
|
if (fOffset + count > fSize) {
|
||||||
|
count = fSize - fOffset;
|
||||||
|
}
|
||||||
|
size_t bytesLeftToRead = count;
|
||||||
|
while (fCurrent != NULL) {
|
||||||
|
size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
|
||||||
|
size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent
|
||||||
|
? bytesLeftToRead : bytesLeftInCurrent;
|
||||||
|
if (buffer) {
|
||||||
|
memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
|
||||||
|
}
|
||||||
|
if (bytesLeftToRead <= bytesFromCurrent) {
|
||||||
|
fCurrentOffset += bytesFromCurrent;
|
||||||
|
fOffset += count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
bytesLeftToRead -= bytesFromCurrent;
|
||||||
|
buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
|
||||||
|
fCurrent = fCurrent->fNext;
|
||||||
|
fCurrentOffset = 0;
|
||||||
|
}
|
||||||
|
SkASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isAtEnd() const SK_OVERRIDE {
|
||||||
|
return fOffset == fSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool rewind() SK_OVERRIDE {
|
||||||
|
fCurrent = fBlockMemory->fHead;
|
||||||
|
fOffset = 0;
|
||||||
|
fCurrentOffset = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
|
||||||
|
return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t getPosition() const SK_OVERRIDE {
|
||||||
|
return fOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool seek(size_t position) SK_OVERRIDE {
|
||||||
|
// If possible, skip forward.
|
||||||
|
if (position >= fOffset) {
|
||||||
|
size_t skipAmount = position - fOffset;
|
||||||
|
return this->skip(skipAmount) == skipAmount;
|
||||||
|
}
|
||||||
|
// If possible, move backward within the current block.
|
||||||
|
size_t moveBackAmount = fOffset - position;
|
||||||
|
if (moveBackAmount <= fCurrentOffset) {
|
||||||
|
fCurrentOffset -= moveBackAmount;
|
||||||
|
fOffset -= moveBackAmount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Otherwise rewind and move forward.
|
||||||
|
return this->rewind() && this->skip(position) == position;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool move(long offset) SK_OVERRIDE {
|
||||||
|
return seek(fOffset + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
|
||||||
|
SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
|
||||||
|
that->fCurrent = this->fCurrent;
|
||||||
|
that->fOffset = this->fOffset;
|
||||||
|
that->fCurrentOffset = this->fCurrentOffset;
|
||||||
|
return that.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t getLength() const SK_OVERRIDE {
|
||||||
|
return fSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const void* getMemoryBase() SK_OVERRIDE {
|
||||||
|
if (NULL == fBlockMemory->fHead->fNext) {
|
||||||
|
return fBlockMemory->fHead->start();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
|
||||||
|
SkDynamicMemoryWStream::Block const * fCurrent;
|
||||||
|
size_t const fSize;
|
||||||
|
size_t fOffset;
|
||||||
|
size_t fCurrentOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
SkStreamAsset* SkDynamicMemoryWStream::detatchAsStream() {
|
||||||
|
if (fCopy) {
|
||||||
|
SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
|
||||||
|
this->reset();
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
|
||||||
|
fHead = 0;
|
||||||
|
this->reset();
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SkDebugWStream::newline()
|
void SkDebugWStream::newline()
|
||||||
|
@ -30,6 +30,7 @@ static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// expect EOF
|
// expect EOF
|
||||||
|
REPORTER_ASSERT(reporter, stream->isAtEnd());
|
||||||
size_t bytes = stream->read(tmp, 1);
|
size_t bytes = stream->read(tmp, 1);
|
||||||
REPORTER_ASSERT(reporter, 0 == bytes);
|
REPORTER_ASSERT(reporter, 0 == bytes);
|
||||||
}
|
}
|
||||||
@ -81,6 +82,7 @@ static void TestWStream(skiatest::Reporter* reporter) {
|
|||||||
REPORTER_ASSERT(reporter, ds.write(s, 26));
|
REPORTER_ASSERT(reporter, ds.write(s, 26));
|
||||||
}
|
}
|
||||||
REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
|
REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
|
||||||
|
|
||||||
char* dst = new char[100 * 26 + 1];
|
char* dst = new char[100 * 26 + 1];
|
||||||
dst[100*26] = '*';
|
dst[100*26] = '*';
|
||||||
ds.copyTo(dst);
|
ds.copyTo(dst);
|
||||||
@ -90,10 +92,42 @@ static void TestWStream(skiatest::Reporter* reporter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SkData* data = ds.copyToData();
|
SkAutoTUnref<SkStreamAsset> stream(ds.detatchAsStream());
|
||||||
|
REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
|
||||||
|
REPORTER_ASSERT(reporter, ds.getOffset() == 0);
|
||||||
|
test_loop_stream(reporter, stream.get(), s, 26, 100);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate());
|
||||||
|
test_loop_stream(reporter, stream2.get(), s, 26, 100);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStreamAsset> stream3(stream->fork());
|
||||||
|
REPORTER_ASSERT(reporter, stream3->isAtEnd());
|
||||||
|
char tmp;
|
||||||
|
size_t bytes = stream->read(&tmp, 1);
|
||||||
|
REPORTER_ASSERT(reporter, 0 == bytes);
|
||||||
|
stream3->rewind();
|
||||||
|
test_loop_stream(reporter, stream3.get(), s, 26, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 100; i++) {
|
||||||
|
REPORTER_ASSERT(reporter, ds.write(s, 26));
|
||||||
|
}
|
||||||
|
REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
|
||||||
|
|
||||||
|
{
|
||||||
|
SkAutoTUnref<SkData> data(ds.copyToData());
|
||||||
REPORTER_ASSERT(reporter, 100 * 26 == data->size());
|
REPORTER_ASSERT(reporter, 100 * 26 == data->size());
|
||||||
REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0);
|
REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0);
|
||||||
data->unref();
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test that this works after a copyToData.
|
||||||
|
SkAutoTUnref<SkStreamAsset> stream(ds.detatchAsStream());
|
||||||
|
REPORTER_ASSERT(reporter, ds.getOffset() == 0);
|
||||||
|
test_loop_stream(reporter, stream.get(), s, 26, 100);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate());
|
||||||
|
test_loop_stream(reporter, stream2.get(), s, 26, 100);
|
||||||
}
|
}
|
||||||
delete[] dst;
|
delete[] dst;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user