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:
parent
8fd48b8bd8
commit
9df621da50
@ -6,6 +6,9 @@
|
||||
{
|
||||
'target_name': 'images',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'utils.gyp:utils',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include/config',
|
||||
'../include/core',
|
||||
|
@ -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': {
|
||||
|
37
include/utils/win/SkAutoCoInitialize.h
Normal file
37
include/utils/win/SkAutoCoInitialize.h
Normal 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
|
135
include/utils/win/SkIStream.h
Normal file
135
include/utils/win/SkIStream.h
Normal 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
|
47
include/utils/win/SkTScopedComPtr.h
Normal file
47
include/utils/win/SkTScopedComPtr.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
34
src/utils/win/SkAutoCoInitialize.cpp
Normal file
34
src/utils/win/SkAutoCoInitialize.cpp
Normal 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
263
src/utils/win/SkIStream.cpp
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user