diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/utils/win/SkIStream.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/utils/win/SkIStream.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,277 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "SkIStream.h" +#include "SkStream.h" + +/** + * SkBaseIStream + */ +SkBaseIStream::SkBaseIStream() : _refcount(1) { } +SkBaseIStream::~SkBaseIStream() { } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid + , void ** ppvObject) +{ + if (NULL == ppvObject) { + return E_INVALIDARG; + } + if (iid == __uuidof(IUnknown) + || iid == __uuidof(IStream) + || iid == __uuidof(ISequentialStream)) + { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } else { + *ppvObject = NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) { + return (ULONG)InterlockedIncrement(&_refcount); +} + +ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) { + ULONG res = (ULONG) InterlockedDecrement(&_refcount); + if (0 == res) { + delete this; + } + return res; +} + +// ISequentialStream Interface +HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv + , ULONG cb + , ULONG* pcbRead) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv + , ULONG cb + , ULONG* pcbWritten) +{ return E_NOTIMPL; } + +// IStream Interface +HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream* + , ULARGE_INTEGER + , ULARGE_INTEGER* + , ULARGE_INTEGER*) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER + , ULARGE_INTEGER + , DWORD) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER + , ULARGE_INTEGER + , DWORD) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove + , DWORD dwOrigin + , ULARGE_INTEGER* lpNewFilePointer) +{ return E_NOTIMPL; } + +HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg + , DWORD grfStatFlag) +{ return E_NOTIMPL; } + + +/** + * SkIStream + */ +SkIStream::SkIStream(SkStream* stream, bool unrefOnRelease) + : SkBaseIStream() + , fSkStream(stream) + , fUnrefOnRelease(unrefOnRelease) + , fLocation() +{ + this->fSkStream->rewind(); +} + +SkIStream::~SkIStream() { + if (NULL != this->fSkStream && fUnrefOnRelease) { + this->fSkStream->unref(); + } +} + +HRESULT SkIStream::CreateFromSkStream(SkStream* stream + , bool unrefOnRelease + , IStream ** ppStream) +{ + if (NULL == stream) { + return E_INVALIDARG; + } + *ppStream = new SkIStream(stream, unrefOnRelease); + return S_OK; +} + +// ISequentialStream Interface +HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) { + *pcbRead = static_cast(this->fSkStream->read(pv, cb)); + this->fLocation.QuadPart += *pcbRead; + return (*pcbRead == cb) ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv + , ULONG cb + , ULONG* pcbWritten) +{ + return STG_E_CANTSAVE; +} + +// IStream Interface +HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove + , DWORD dwOrigin + , ULARGE_INTEGER* lpNewFilePointer) +{ + HRESULT hr = S_OK; + + switch(dwOrigin) { + case STREAM_SEEK_SET: { + if (!this->fSkStream->rewind()) { + hr = E_FAIL; + } else { + size_t skipped = this->fSkStream->skip( + static_cast(liDistanceToMove.QuadPart) + ); + this->fLocation.QuadPart = skipped; + if (skipped != liDistanceToMove.QuadPart) { + hr = E_FAIL; + } + } + break; + } + case STREAM_SEEK_CUR: { + size_t skipped = this->fSkStream->skip( + static_cast(liDistanceToMove.QuadPart) + ); + this->fLocation.QuadPart += skipped; + if (skipped != liDistanceToMove.QuadPart) { + hr = E_FAIL; + } + break; + } + case STREAM_SEEK_END: { + if (!this->fSkStream->rewind()) { + hr = E_FAIL; + } else { + // FIXME: Should not depend on getLength. + // See https://code.google.com/p/skia/issues/detail?id=1570 + LONGLONG skip = this->fSkStream->getLength() + + liDistanceToMove.QuadPart; + size_t skipped = this->fSkStream->skip(static_cast(skip)); + this->fLocation.QuadPart = skipped; + if (skipped != skip) { + hr = E_FAIL; + } + } + break; + } + default: + hr = STG_E_INVALIDFUNCTION; + break; + } + + if (NULL != lpNewFilePointer) { + lpNewFilePointer->QuadPart = this->fLocation.QuadPart; + } + return hr; +} + +HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg + , DWORD grfStatFlag) +{ + if (0 == (grfStatFlag & STATFLAG_NONAME)) { + return STG_E_INVALIDFLAG; + } + pStatstg->pwcsName = NULL; + // FIXME: Should not depend on getLength + // See https://code.google.com/p/skia/issues/detail?id=1570 + pStatstg->cbSize.QuadPart = this->fSkStream->getLength(); + pStatstg->clsid = CLSID_NULL; + pStatstg->type = STGTY_STREAM; + pStatstg->grfMode = STGM_READ; + return S_OK; +} + + +/** + * SkIWStream + */ +SkWIStream::SkWIStream(SkWStream* stream) + : SkBaseIStream() + , fSkWStream(stream) +{ } + +SkWIStream::~SkWIStream() { + if (NULL != this->fSkWStream) { + this->fSkWStream->flush(); + } +} + +HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream + , IStream ** ppStream) +{ + *ppStream = new SkWIStream(stream); + return S_OK; +} + +// ISequentialStream Interface +HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv + , ULONG cb + , ULONG* pcbWritten) +{ + HRESULT hr = S_OK; + bool wrote = this->fSkWStream->write(pv, cb); + if (wrote) { + *pcbWritten = cb; + } else { + *pcbWritten = 0; + hr = S_FALSE; + } + return hr; +} + +// IStream Interface +HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) { + this->fSkWStream->flush(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg + , DWORD grfStatFlag) +{ + if (0 == (grfStatFlag & STATFLAG_NONAME)) { + return STG_E_INVALIDFLAG; + } + pStatstg->pwcsName = NULL; + pStatstg->cbSize.QuadPart = 0; + pStatstg->clsid = CLSID_NULL; + pStatstg->type = STGTY_STREAM; + pStatstg->grfMode = STGM_WRITE; + return S_OK; +}