Wrap SkStreams in IStreams instead of copying data around.

http://codereview.appspot.com/4630062/


git-svn-id: http://skia.googlecode.com/svn/trunk@1694 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2011-06-23 21:43:52 +00:00
parent 8fd48b8bd8
commit 9df621da50
8 changed files with 586 additions and 187 deletions

View File

@ -6,6 +6,9 @@
{
'target_name': 'images',
'type': 'static_library',
'dependencies': [
'utils.gyp:utils',
],
'include_dirs': [
'../include/config',
'../include/core',

View File

@ -12,6 +12,7 @@
'../include/utils',
'../include/utils/mac',
'../include/utils/unix',
'../include/utils/win',
'../include/views',
'../include/effects',
'../include/xml',
@ -59,22 +60,32 @@
'../src/utils/SkSfntUtils.cpp',
'../src/utils/SkUnitMappers.cpp',
#mac
'../include/utils/mac/SkCGUtils.h',
'../src/utils/mac/SkCreateCGImageRef.cpp',
'../src/utils/mac/SkEGLContext_mac.cpp',
'../src/utils/mac/skia_mac.cpp',
'../src/utils/mac/SkOSWindow_Mac.cpp',
#mesa
'../src/utils/mesa/SkEGLContext_Mesa.cpp',
#sdl
'../src/utils/SDL/SkOSWindow_SDL.cpp',
#*nix
'../src/utils/unix/keysym2ucs.c',
'../src/utils/unix/SkEGLContext_Unix.cpp',
'../src/utils/unix/SkOSWindow_Unix.cpp',
#windows
'../include/utils/win/SkAutoCoInitialize.h',
'../include/utils/win/SkIStream.h',
'../include/utils/win/SkTScopedComPtr.h',
'../src/utils/win/SkAutoCoInitialize.cpp',
'../src/utils/win/skia_win.cpp',
'../src/utils/win/SkEGLContext_Win.cpp',
'../src/utils/win/SkIStream.cpp',
'../src/utils/win/SkOSWindow_Win.cpp',
],
'sources!': [
@ -82,18 +93,6 @@
'../src/utils/SDL/SkOSWindow_SDL.cpp',
],
'conditions': [
[ 'OS != "mac"', {
'sources!': [
'../include/utils/mac/SkCGUtils.h',
'../src/utils/mac/SkCreateCGImageRef.cpp',
'../src/utils/mac/SkEGLContext_mac.cpp',
'../src/utils/mac/skia_mac.cpp',
'../src/utils/mac/SkOSWindow_Mac.cpp',
],
'include_dirs!': [
'../include/utils/mac',
],
}],
[ 'OS == "mac"', {
'sources!': [
'../src/utils/SkEGLContext_none.cpp',
@ -103,18 +102,19 @@
'$(SDKROOT)/System/Library/Frameworks/AGL.framework',
],
},
}],
[ 'OS != "linux" and OS != "freebsd" and OS != "openbsd" and OS != "solaris"', {
'sources!': [
'../src/utils/unix/keysym2ucs.c',
'../src/utils/unix/SkEGLContext_Unix.cpp',
'../src/utils/unix/SkOSWindow_Unix.cpp',
],
},{ #else if 'OS != "mac"'
'include_dirs!': [
'../include/utils/unix',
'../include/utils/mac',
],
'sources!': [
'../include/utils/mac/SkCGUtils.h',
'../src/utils/mac/SkCreateCGImageRef.cpp',
'../src/utils/mac/SkEGLContext_mac.cpp',
'../src/utils/mac/skia_mac.cpp',
'../src/utils/mac/SkOSWindow_Mac.cpp',
],
}],
[ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', {
[ 'OS in ["linux", "freebsd", "openbsd", "solaris"]', {
'sources!': [
'../src/utils/SkEGLContext_none.cpp',
],
@ -124,18 +124,39 @@
'-lGLU',
],
},
}],
[ 'OS != "win"', {
},{ #else if 'OS not in ["linux", "freebsd", "openbsd", "solaris"]'
'include_dirs!': [
'../include/utils/unix',
],
'sources!': [
'../src/utils/win/skia_win.cpp',
'../src/utils/win/SkEGLContext_Win.cpp',
'../src/utils/win/SkOSWindow_Win.cpp',
'../src/utils/unix/keysym2ucs.c',
'../src/utils/unix/SkEGLContext_Unix.cpp',
'../src/utils/unix/SkOSWindow_Unix.cpp',
],
}],
[ 'OS == "win"', {
'sources!': [
'../src/utils/SkEGLContext_none.cpp',
],
'direct_dependent_settings': {
'include_dirs': [
'../include/utils/win',
],
},
},{ #else if 'OS != "win"'
'include_dirs!': [
'../include/utils/win',
],
'sources!': [
'../include/utils/win/SkAutoCoInitialize.h',
'../include/utils/win/SkIStream.h',
'../include/utils/win/SkTScopedComPtr.h',
'../src/utils/win/SkAutoCoInitialize.cpp',
'../src/utils/win/skia_win.cpp',
'../src/utils/win/SkEGLContext_Win.cpp',
'../src/utils/win/SkIStream.cpp',
'../src/utils/win/SkOSWindow_Win.cpp',
],
}],
],
'direct_dependent_settings': {

View File

@ -0,0 +1,37 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SkAutoCo_DEFINED
#define SkAutoCo_DEFINED
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "SkTemplates.h"
/**
* An instance of this class initializes COM on creation
* and closes the COM library on destruction.
*/
class AutoCoInitialize : SkNoncopyable {
private:
HRESULT fHR;
public:
AutoCoInitialize();
~AutoCoInitialize();
HRESULT getHR();
};
#endif

View File

@ -0,0 +1,135 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SkIStream_DEFINED
#define SkIStream_DEFINED
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <ole2.h>
class SkStream;
class SkWStream;
/**
* A bare IStream implementation which properly reference counts
* but returns E_NOTIMPL for all ISequentialStream and IStream methods.
*/
class SkBaseIStream : public IStream {
private:
LONG _refcount;
protected:
explicit SkBaseIStream();
virtual ~SkBaseIStream();
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid
, void ** ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef(void);
virtual ULONG STDMETHODCALLTYPE Release(void);
// ISequentialStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead);
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
, ULONG cb
, ULONG* pcbWritten);
// IStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER);
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*
, ULARGE_INTEGER
, ULARGE_INTEGER*
, ULARGE_INTEGER*);
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD);
virtual HRESULT STDMETHODCALLTYPE Revert(void);
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER
, ULARGE_INTEGER
, DWORD);
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER
, ULARGE_INTEGER
, DWORD);
virtual HRESULT STDMETHODCALLTYPE Clone(IStream **);
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove
, DWORD dwOrigin
, ULARGE_INTEGER* lpNewFilePointer);
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
, DWORD grfStatFlag);
};
/**
* A minimal read-only IStream implementation which wraps an SkIStream.
*/
class SkIStream : public SkBaseIStream {
private:
SkStream *fSkStream;
bool fUnrefOnRelease;
SkIStream(SkStream* stream, bool unrefOnRelease);
virtual ~SkIStream();
public:
HRESULT static CreateFromSkStream(SkStream* stream
, bool unrefOnRelease
, IStream ** ppStream);
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead);
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
, ULONG cb
, ULONG* pcbWritten);
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove
, DWORD dwOrigin
, ULARGE_INTEGER* lpNewFilePointer);
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
, DWORD grfStatFlag);
};
/**
* A minimal write-only IStream implementation which wraps an SkWIStream.
*/
class SkWIStream : public SkBaseIStream {
private:
SkWStream *fSkWStream;
SkWIStream(SkWStream* stream);
virtual ~SkWIStream();
public:
HRESULT static CreateFromSkWStream(SkWStream* stream, IStream ** ppStream);
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
, ULONG cb
, ULONG* pcbWritten);
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
, DWORD grfStatFlag);
};
#endif

View File

@ -0,0 +1,47 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SkSkTScopedPtr_DEFINED
#define SkSkTScopedPtr_DEFINED
#include "SkTemplates.h"
template<typename T>
class SkTScopedComPtr : SkNoncopyable {
private:
T *fPtr;
public:
explicit SkTScopedComPtr(T *ptr = NULL) : fPtr(ptr) { }
~SkTScopedComPtr() {
if (NULL != fPtr) {
fPtr->Release();
fPtr = NULL;
}
}
T &operator*() const { return *fPtr; }
T *operator->() const { return fPtr; }
/**
* Returns the address of the underlying pointer.
* This is dangerous -- it breaks encapsulation and the reference escapes.
* Must only be used on instances currently pointing to NULL,
* and only to initialize the instance.
*/
T **operator&() { SkASSERT(fPtr == NULL); return &fPtr; }
T *get() const { return fPtr; }
};
#endif

View File

@ -1,5 +1,5 @@
/*
Copyright 2010 Google Inc.
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,137 +17,26 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <wincodec.h>
#include "SkAutoCoInitialize.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkIStream.h"
#include "SkMovie.h"
#include "SkStream.h"
#include "SkTemplates.h"
template<typename T>
class scoped_com_ptr {
private:
T *fPtr;
scoped_com_ptr(scoped_com_ptr const &);
scoped_com_ptr & operator=(scoped_com_ptr const &);
public:
explicit scoped_com_ptr(T *ptr = NULL) : fPtr(ptr) { }
~scoped_com_ptr() {
if (NULL != fPtr) {
fPtr->Release();
fPtr = NULL;
}
}
T &operator*() const { return *fPtr; }
T *operator->() const { return fPtr; }
/**
* Returns the address of the underlying pointer.
* This is dangerous -- it breaks encapsulation and the reference escapes.
* Must only be used on instances currently pointing to NULL,
* and only to initialize the instance.
*/
T **operator&() { SkASSERT(fPtr == NULL); return &fPtr; }
T *get() const { return fPtr; }
};
/**
* An instance of this class initializes COM on creation
* and closes the COM library on destruction.
*/
class AutoCoInitialize : SkNoncopyable {
private:
HRESULT hr;
public:
AutoCoInitialize() :
hr(
CoInitializeEx(
NULL
, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE
)
)
{ }
~AutoCoInitialize() {
if (SUCCEEDED(this->hr)) {
CoUninitialize();
}
}
HRESULT getHR() { return this->hr; }
};
#include "SkTScopedComPtr.h"
class SkImageDecoder_WIC : public SkImageDecoder {
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};
/**
* Converts a SkStream to an IStream.
* The caller must call Release() on the returned IStream.
*/
static HRESULT SkStreamToIStream(SkStream* stream, IStream** ppStream) {
//TODO(bungeman): use a real IStream wrapper
HRESULT hr = S_OK;
size_t len = stream->getLength();
//Reserve memory for content of IStream.
HGLOBAL hdata = NULL;
if (SUCCEEDED(hr)) {
hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, len);
if (NULL == hdata) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
//Lock memory.
void* data = NULL;
if (SUCCEEDED(hr)) {
data = GlobalLock(hdata);
if (NULL == data) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
//Write SkStream data to memory.
if (SUCCEEDED(hr)) {
size_t read = stream->read(data, len);
if (read != len) {
hr = E_FAIL;
}
}
//Unlock memory.
if (NULL != data) {
data = NULL;
SetLastError(NO_ERROR);
GlobalUnlock(hdata);
DWORD lastError = GetLastError();
if (SUCCEEDED(hr) && NO_ERROR != lastError) {
hr = HRESULT_FROM_WIN32(lastError);
}
}
//Create IStream from memory.
if (SUCCEEDED(hr)) {
hr = CreateStreamOnHGlobal(hdata, TRUE, ppStream);
}
//If we failed for any reason, free the memory.
if (FAILED(hr)) {
if (NULL != hdata) {
GlobalFree(hdata);
}
}
return hr;
}
bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
//Initialize COM.
AutoCoInitialize scopedCo;
HRESULT hr = scopedCo.getHR();
//Create Windows Imaging Component ImagingFactory.
scoped_com_ptr<IWICImagingFactory> piImagingFactory;
SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
if (SUCCEEDED(hr)) {
hr = CoCreateInstance(
CLSID_WICImagingFactory
@ -158,9 +47,9 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
}
//Convert SkStream to IStream.
scoped_com_ptr<IStream> piStream;
SkTScopedComPtr<IStream> piStream;
if (SUCCEEDED(hr)) {
hr = SkStreamToIStream(stream, &piStream);
hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
}
//Make sure we're at the beginning of the stream.
@ -170,7 +59,7 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
}
//Create the decoder from the stream content.
scoped_com_ptr<IWICBitmapDecoder> piBitmapDecoder;
SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
if (SUCCEEDED(hr)) {
hr = piImagingFactory->CreateDecoderFromStream(
piStream.get() //Image to be decoded
@ -181,13 +70,13 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
}
//Get the first frame from the decoder.
scoped_com_ptr<IWICBitmapFrameDecode> piBitmapFrameDecode;
SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
if (SUCCEEDED(hr)) {
hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
}
//Get the BitmapSource interface of the frame.
scoped_com_ptr<IWICBitmapSource> piBitmapSourceOriginal;
SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
if (SUCCEEDED(hr)) {
hr = piBitmapFrameDecode->QueryInterface(
IID_PPV_ARGS(&piBitmapSourceOriginal)
@ -213,7 +102,7 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
}
//Create a format converter.
scoped_com_ptr<IWICFormatConverter> piFormatConverter;
SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
if (SUCCEEDED(hr)) {
hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
}
@ -230,7 +119,7 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
}
//Get the BitmapSource interface of the format converter.
scoped_com_ptr<IWICBitmapSource> piBitmapSourceConverted;
SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
if (SUCCEEDED(hr)) {
hr = piFormatConverter->QueryInterface(
IID_PPV_ARGS(&piBitmapSourceConverted)
@ -300,7 +189,7 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream
HRESULT hr = scopedCo.getHR();
//Create Windows Imaging Component ImagingFactory.
scoped_com_ptr<IWICImagingFactory> piImagingFactory;
SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
if (SUCCEEDED(hr)) {
hr = CoCreateInstance(
CLSID_WICImagingFactory
@ -310,14 +199,14 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream
);
}
//Create the stream to hold the output of the encoder.
scoped_com_ptr<IStream> piStream;
//Convert the SkWStream to an IStream.
SkTScopedComPtr<IStream> piStream;
if (SUCCEEDED(hr)) {
hr = CreateStreamOnHGlobal(NULL, TRUE, &piStream);
hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
}
//Create an encode of the appropriate type.
scoped_com_ptr<IWICBitmapEncoder> piEncoder;
SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
if (SUCCEEDED(hr)) {
hr = piImagingFactory->CreateEncoder(type, NULL, &piEncoder);
}
@ -327,8 +216,8 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream
}
//Create a the frame.
scoped_com_ptr<IWICBitmapFrameEncode> piBitmapFrameEncode;
scoped_com_ptr<IPropertyBag2> piPropertybag;
SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
SkTScopedComPtr<IPropertyBag2> piPropertybag;
if (SUCCEEDED(hr)) {
hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
}
@ -389,36 +278,6 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream
hr = piEncoder->Commit();
}
//Rewind the IStream with the output of the encoder.
if (SUCCEEDED(hr)) {
LARGE_INTEGER liBeginning = { 0 };
hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, NULL);
}
//Write the content of the IStream to the SkWStream.
if (SUCCEEDED(hr)) {
//TODO(bungeman): use a real IStream(SkWStream) wrapper
const unsigned int BUFFER_SIZE = 1024;
void* buffer = new BYTE[BUFFER_SIZE];
ULONG bytesRead = 0;
while (true) {
hr = piStream->Read(buffer, BUFFER_SIZE, &bytesRead);
if (FAILED(hr)) {
break;
}
bool wrote = stream->write(buffer, bytesRead);
if (!wrote) {
hr = E_FAIL;
break;
}
if (BUFFER_SIZE != bytesRead) {
break;
}
}
stream->flush();
delete[] buffer;
}
return SUCCEEDED(hr);
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <ole2.h>
#include "SkAutoCoInitialize.h"
AutoCoInitialize::AutoCoInitialize() :
fHR(
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
)
{ }
AutoCoInitialize::~AutoCoInitialize() {
if (SUCCEEDED(this->fHR)) {
CoUninitialize();
}
}
HRESULT AutoCoInitialize::getHR() { return this->fHR; }

263
src/utils/win/SkIStream.cpp Normal file
View File

@ -0,0 +1,263 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <ole2.h>
#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<IStream*>(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)
{ }
SkIStream::~SkIStream() {
if (NULL != this->fSkStream && fUnrefOnRelease) {
this->fSkStream->unref();
}
}
HRESULT SkIStream::CreateFromSkStream(SkStream* stream
, bool unrefOnRelease
, IStream ** ppStream)
{
*ppStream = new SkIStream(stream, unrefOnRelease);
return S_OK;
}
// ISequentialStream Interface
HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
*pcbRead = this->fSkStream->read(pv, cb);
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)
{
if (lpNewFilePointer != NULL) {
(*lpNewFilePointer).QuadPart = NULL;
}
HRESULT hr = S_OK;
switch(dwOrigin) {
case STREAM_SEEK_SET: {
if (!this->fSkStream->rewind()) {
hr = E_FAIL;
} else {
size_t skipped = this->fSkStream->skip(
liDistanceToMove.QuadPart
);
if (skipped != liDistanceToMove.QuadPart) {
hr = E_FAIL;
}
}
break;
}
case STREAM_SEEK_CUR: {
size_t skipped = this->fSkStream->skip(liDistanceToMove.QuadPart);
if (skipped != liDistanceToMove.QuadPart) {
hr = E_FAIL;
}
break;
}
case STREAM_SEEK_END: {
if (!this->fSkStream->rewind()) {
hr = E_FAIL;
} else {
size_t skipped = this->fSkStream->skip(
this->fSkStream->getLength() + liDistanceToMove.QuadPart
);
if (skipped != liDistanceToMove.QuadPart) {
hr = E_FAIL;
}
}
break;
}
default:
hr = STG_E_INVALIDFUNCTION;
break;
}
return hr;
}
HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
, DWORD grfStatFlag)
{
if (0 == grfStatFlag & STATFLAG_NONAME) {
return STG_E_INVALIDFLAG;
}
pStatstg->pwcsName = NULL;
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::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;
}