1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/win/SkIStream.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,277 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#define WIN32_LEAN_AND_MEAN 1.14 +#include <windows.h> 1.15 +#include <ole2.h> 1.16 +#include "SkIStream.h" 1.17 +#include "SkStream.h" 1.18 + 1.19 +/** 1.20 + * SkBaseIStream 1.21 + */ 1.22 +SkBaseIStream::SkBaseIStream() : _refcount(1) { } 1.23 +SkBaseIStream::~SkBaseIStream() { } 1.24 + 1.25 +HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid 1.26 + , void ** ppvObject) 1.27 +{ 1.28 + if (NULL == ppvObject) { 1.29 + return E_INVALIDARG; 1.30 + } 1.31 + if (iid == __uuidof(IUnknown) 1.32 + || iid == __uuidof(IStream) 1.33 + || iid == __uuidof(ISequentialStream)) 1.34 + { 1.35 + *ppvObject = static_cast<IStream*>(this); 1.36 + AddRef(); 1.37 + return S_OK; 1.38 + } else { 1.39 + *ppvObject = NULL; 1.40 + return E_NOINTERFACE; 1.41 + } 1.42 +} 1.43 + 1.44 +ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) { 1.45 + return (ULONG)InterlockedIncrement(&_refcount); 1.46 +} 1.47 + 1.48 +ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) { 1.49 + ULONG res = (ULONG) InterlockedDecrement(&_refcount); 1.50 + if (0 == res) { 1.51 + delete this; 1.52 + } 1.53 + return res; 1.54 +} 1.55 + 1.56 +// ISequentialStream Interface 1.57 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv 1.58 + , ULONG cb 1.59 + , ULONG* pcbRead) 1.60 +{ return E_NOTIMPL; } 1.61 + 1.62 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv 1.63 + , ULONG cb 1.64 + , ULONG* pcbWritten) 1.65 +{ return E_NOTIMPL; } 1.66 + 1.67 +// IStream Interface 1.68 +HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER) 1.69 +{ return E_NOTIMPL; } 1.70 + 1.71 +HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream* 1.72 + , ULARGE_INTEGER 1.73 + , ULARGE_INTEGER* 1.74 + , ULARGE_INTEGER*) 1.75 +{ return E_NOTIMPL; } 1.76 + 1.77 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD) 1.78 +{ return E_NOTIMPL; } 1.79 + 1.80 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void) 1.81 +{ return E_NOTIMPL; } 1.82 + 1.83 +HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER 1.84 + , ULARGE_INTEGER 1.85 + , DWORD) 1.86 +{ return E_NOTIMPL; } 1.87 + 1.88 +HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER 1.89 + , ULARGE_INTEGER 1.90 + , DWORD) 1.91 +{ return E_NOTIMPL; } 1.92 + 1.93 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **) 1.94 +{ return E_NOTIMPL; } 1.95 + 1.96 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove 1.97 + , DWORD dwOrigin 1.98 + , ULARGE_INTEGER* lpNewFilePointer) 1.99 +{ return E_NOTIMPL; } 1.100 + 1.101 +HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg 1.102 + , DWORD grfStatFlag) 1.103 +{ return E_NOTIMPL; } 1.104 + 1.105 + 1.106 +/** 1.107 + * SkIStream 1.108 + */ 1.109 +SkIStream::SkIStream(SkStream* stream, bool unrefOnRelease) 1.110 + : SkBaseIStream() 1.111 + , fSkStream(stream) 1.112 + , fUnrefOnRelease(unrefOnRelease) 1.113 + , fLocation() 1.114 +{ 1.115 + this->fSkStream->rewind(); 1.116 +} 1.117 + 1.118 +SkIStream::~SkIStream() { 1.119 + if (NULL != this->fSkStream && fUnrefOnRelease) { 1.120 + this->fSkStream->unref(); 1.121 + } 1.122 +} 1.123 + 1.124 +HRESULT SkIStream::CreateFromSkStream(SkStream* stream 1.125 + , bool unrefOnRelease 1.126 + , IStream ** ppStream) 1.127 +{ 1.128 + if (NULL == stream) { 1.129 + return E_INVALIDARG; 1.130 + } 1.131 + *ppStream = new SkIStream(stream, unrefOnRelease); 1.132 + return S_OK; 1.133 +} 1.134 + 1.135 +// ISequentialStream Interface 1.136 +HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) { 1.137 + *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb)); 1.138 + this->fLocation.QuadPart += *pcbRead; 1.139 + return (*pcbRead == cb) ? S_OK : S_FALSE; 1.140 +} 1.141 + 1.142 +HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv 1.143 + , ULONG cb 1.144 + , ULONG* pcbWritten) 1.145 +{ 1.146 + return STG_E_CANTSAVE; 1.147 +} 1.148 + 1.149 +// IStream Interface 1.150 +HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove 1.151 + , DWORD dwOrigin 1.152 + , ULARGE_INTEGER* lpNewFilePointer) 1.153 +{ 1.154 + HRESULT hr = S_OK; 1.155 + 1.156 + switch(dwOrigin) { 1.157 + case STREAM_SEEK_SET: { 1.158 + if (!this->fSkStream->rewind()) { 1.159 + hr = E_FAIL; 1.160 + } else { 1.161 + size_t skipped = this->fSkStream->skip( 1.162 + static_cast<size_t>(liDistanceToMove.QuadPart) 1.163 + ); 1.164 + this->fLocation.QuadPart = skipped; 1.165 + if (skipped != liDistanceToMove.QuadPart) { 1.166 + hr = E_FAIL; 1.167 + } 1.168 + } 1.169 + break; 1.170 + } 1.171 + case STREAM_SEEK_CUR: { 1.172 + size_t skipped = this->fSkStream->skip( 1.173 + static_cast<size_t>(liDistanceToMove.QuadPart) 1.174 + ); 1.175 + this->fLocation.QuadPart += skipped; 1.176 + if (skipped != liDistanceToMove.QuadPart) { 1.177 + hr = E_FAIL; 1.178 + } 1.179 + break; 1.180 + } 1.181 + case STREAM_SEEK_END: { 1.182 + if (!this->fSkStream->rewind()) { 1.183 + hr = E_FAIL; 1.184 + } else { 1.185 + // FIXME: Should not depend on getLength. 1.186 + // See https://code.google.com/p/skia/issues/detail?id=1570 1.187 + LONGLONG skip = this->fSkStream->getLength() 1.188 + + liDistanceToMove.QuadPart; 1.189 + size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip)); 1.190 + this->fLocation.QuadPart = skipped; 1.191 + if (skipped != skip) { 1.192 + hr = E_FAIL; 1.193 + } 1.194 + } 1.195 + break; 1.196 + } 1.197 + default: 1.198 + hr = STG_E_INVALIDFUNCTION; 1.199 + break; 1.200 + } 1.201 + 1.202 + if (NULL != lpNewFilePointer) { 1.203 + lpNewFilePointer->QuadPart = this->fLocation.QuadPart; 1.204 + } 1.205 + return hr; 1.206 +} 1.207 + 1.208 +HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg 1.209 + , DWORD grfStatFlag) 1.210 +{ 1.211 + if (0 == (grfStatFlag & STATFLAG_NONAME)) { 1.212 + return STG_E_INVALIDFLAG; 1.213 + } 1.214 + pStatstg->pwcsName = NULL; 1.215 + // FIXME: Should not depend on getLength 1.216 + // See https://code.google.com/p/skia/issues/detail?id=1570 1.217 + pStatstg->cbSize.QuadPart = this->fSkStream->getLength(); 1.218 + pStatstg->clsid = CLSID_NULL; 1.219 + pStatstg->type = STGTY_STREAM; 1.220 + pStatstg->grfMode = STGM_READ; 1.221 + return S_OK; 1.222 +} 1.223 + 1.224 + 1.225 +/** 1.226 + * SkIWStream 1.227 + */ 1.228 +SkWIStream::SkWIStream(SkWStream* stream) 1.229 + : SkBaseIStream() 1.230 + , fSkWStream(stream) 1.231 +{ } 1.232 + 1.233 +SkWIStream::~SkWIStream() { 1.234 + if (NULL != this->fSkWStream) { 1.235 + this->fSkWStream->flush(); 1.236 + } 1.237 +} 1.238 + 1.239 +HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream 1.240 + , IStream ** ppStream) 1.241 +{ 1.242 + *ppStream = new SkWIStream(stream); 1.243 + return S_OK; 1.244 +} 1.245 + 1.246 +// ISequentialStream Interface 1.247 +HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv 1.248 + , ULONG cb 1.249 + , ULONG* pcbWritten) 1.250 +{ 1.251 + HRESULT hr = S_OK; 1.252 + bool wrote = this->fSkWStream->write(pv, cb); 1.253 + if (wrote) { 1.254 + *pcbWritten = cb; 1.255 + } else { 1.256 + *pcbWritten = 0; 1.257 + hr = S_FALSE; 1.258 + } 1.259 + return hr; 1.260 +} 1.261 + 1.262 +// IStream Interface 1.263 +HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) { 1.264 + this->fSkWStream->flush(); 1.265 + return S_OK; 1.266 +} 1.267 + 1.268 +HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg 1.269 + , DWORD grfStatFlag) 1.270 +{ 1.271 + if (0 == (grfStatFlag & STATFLAG_NONAME)) { 1.272 + return STG_E_INVALIDFLAG; 1.273 + } 1.274 + pStatstg->pwcsName = NULL; 1.275 + pStatstg->cbSize.QuadPart = 0; 1.276 + pStatstg->clsid = CLSID_NULL; 1.277 + pStatstg->type = STGTY_STREAM; 1.278 + pStatstg->grfMode = STGM_WRITE; 1.279 + return S_OK; 1.280 +}