blob: 560a947fcfbc80fb034c12ea1d5213eddac71069 [file] [log] [blame]
bungeman@google.com9df621d2011-06-23 21:43:52 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
bungeman@google.com9df621d2011-06-23 21:43:52 +00006 */
7
mtklein1ee76512015-11-02 10:20:27 -08008#include "SkTypes.h"
9#if defined(SK_BUILD_FOR_WIN32)
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
bungeman@google.com9df621d2011-06-23 21:43:52 +000011#include "SkIStream.h"
12#include "SkStream.h"
13
14/**
15 * SkBaseIStream
16 */
17SkBaseIStream::SkBaseIStream() : _refcount(1) { }
18SkBaseIStream::~SkBaseIStream() { }
19
20HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
21 , void ** ppvObject)
22{
halcanary96fcdcc2015-08-27 07:41:13 -070023 if (nullptr == ppvObject) {
bungeman@google.com9df621d2011-06-23 21:43:52 +000024 return E_INVALIDARG;
25 }
26 if (iid == __uuidof(IUnknown)
27 || iid == __uuidof(IStream)
28 || iid == __uuidof(ISequentialStream))
29 {
30 *ppvObject = static_cast<IStream*>(this);
31 AddRef();
32 return S_OK;
33 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070034 *ppvObject = nullptr;
rmistry@google.comd6176b02012-08-23 18:14:13 +000035 return E_NOINTERFACE;
bungeman@google.com9df621d2011-06-23 21:43:52 +000036 }
37}
38
39ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
40 return (ULONG)InterlockedIncrement(&_refcount);
41}
42
43ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) {
44 ULONG res = (ULONG) InterlockedDecrement(&_refcount);
45 if (0 == res) {
46 delete this;
47 }
48 return res;
49}
50
51// ISequentialStream Interface
52HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
53 , ULONG cb
54 , ULONG* pcbRead)
55{ return E_NOTIMPL; }
56
57HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
58 , ULONG cb
59 , ULONG* pcbWritten)
60{ return E_NOTIMPL; }
61
62// IStream Interface
rmistry@google.comd6176b02012-08-23 18:14:13 +000063HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
bungeman@google.com9df621d2011-06-23 21:43:52 +000064{ return E_NOTIMPL; }
65
66HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
67 , ULARGE_INTEGER
68 , ULARGE_INTEGER*
69 , ULARGE_INTEGER*)
70{ return E_NOTIMPL; }
71
72HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
73{ return E_NOTIMPL; }
74
75HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
76{ return E_NOTIMPL; }
77
78HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
79 , ULARGE_INTEGER
80 , DWORD)
81{ return E_NOTIMPL; }
82
83HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
84 , ULARGE_INTEGER
85 , DWORD)
86{ return E_NOTIMPL; }
87
88HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
89{ return E_NOTIMPL; }
90
91HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
92 , DWORD dwOrigin
93 , ULARGE_INTEGER* lpNewFilePointer)
94{ return E_NOTIMPL; }
95
96HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
97 , DWORD grfStatFlag)
98{ return E_NOTIMPL; }
99
100
101/**
102 * SkIStream
103 */
bungeman2dca8172015-01-22 06:08:31 -0800104SkIStream::SkIStream(SkStream* stream, bool deleteOnRelease)
bungeman@google.com9df621d2011-06-23 21:43:52 +0000105 : SkBaseIStream()
106 , fSkStream(stream)
bungeman2dca8172015-01-22 06:08:31 -0800107 , fDeleteOnRelease(deleteOnRelease)
bungeman@google.com60157922011-08-13 00:06:17 +0000108 , fLocation()
109{
110 this->fSkStream->rewind();
111}
bungeman@google.com9df621d2011-06-23 21:43:52 +0000112
113SkIStream::~SkIStream() {
bungeman44af7ba2015-01-22 07:33:51 -0800114 if (fDeleteOnRelease) {
bungeman2dca8172015-01-22 06:08:31 -0800115 delete this->fSkStream;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000116 }
117}
118
119HRESULT SkIStream::CreateFromSkStream(SkStream* stream
bungeman2dca8172015-01-22 06:08:31 -0800120 , bool deleteOnRelease
bungeman@google.com9df621d2011-06-23 21:43:52 +0000121 , IStream ** ppStream)
122{
halcanary96fcdcc2015-08-27 07:41:13 -0700123 if (nullptr == stream) {
bungeman@google.com635091f2013-10-01 15:03:18 +0000124 return E_INVALIDARG;
125 }
bungeman2dca8172015-01-22 06:08:31 -0800126 *ppStream = new SkIStream(stream, deleteOnRelease);
bungeman@google.com9df621d2011-06-23 21:43:52 +0000127 return S_OK;
128}
129
130// ISequentialStream Interface
131HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
bungeman@google.com4b18f572013-07-22 15:21:23 +0000132 *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
bungeman@google.com60157922011-08-13 00:06:17 +0000133 this->fLocation.QuadPart += *pcbRead;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000134 return (*pcbRead == cb) ? S_OK : S_FALSE;
135}
136
137HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
138 , ULONG cb
139 , ULONG* pcbWritten)
140{
141 return STG_E_CANTSAVE;
142}
143
144// IStream Interface
145HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
146 , DWORD dwOrigin
147 , ULARGE_INTEGER* lpNewFilePointer)
148{
bungeman@google.com9df621d2011-06-23 21:43:52 +0000149 HRESULT hr = S_OK;
bungeman@google.com60157922011-08-13 00:06:17 +0000150
bungeman@google.com9df621d2011-06-23 21:43:52 +0000151 switch(dwOrigin) {
152 case STREAM_SEEK_SET: {
153 if (!this->fSkStream->rewind()) {
154 hr = E_FAIL;
155 } else {
156 size_t skipped = this->fSkStream->skip(
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000157 static_cast<size_t>(liDistanceToMove.QuadPart)
bungeman@google.com9df621d2011-06-23 21:43:52 +0000158 );
bungeman@google.com60157922011-08-13 00:06:17 +0000159 this->fLocation.QuadPart = skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000160 if (skipped != liDistanceToMove.QuadPart) {
161 hr = E_FAIL;
162 }
163 }
164 break;
165 }
166 case STREAM_SEEK_CUR: {
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000167 size_t skipped = this->fSkStream->skip(
168 static_cast<size_t>(liDistanceToMove.QuadPart)
169 );
bungeman@google.com60157922011-08-13 00:06:17 +0000170 this->fLocation.QuadPart += skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000171 if (skipped != liDistanceToMove.QuadPart) {
172 hr = E_FAIL;
173 }
174 break;
175 }
176 case STREAM_SEEK_END: {
177 if (!this->fSkStream->rewind()) {
178 hr = E_FAIL;
179 } else {
scroggo@google.comb5571b32013-09-25 21:34:24 +0000180 // FIXME: Should not depend on getLength.
181 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com60157922011-08-13 00:06:17 +0000182 LONGLONG skip = this->fSkStream->getLength()
183 + liDistanceToMove.QuadPart;
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000184 size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
bungeman@google.com60157922011-08-13 00:06:17 +0000185 this->fLocation.QuadPart = skipped;
186 if (skipped != skip) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000187 hr = E_FAIL;
188 }
189 }
190 break;
191 }
192 default:
193 hr = STG_E_INVALIDFUNCTION;
194 break;
195 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000196
bsalomon49f085d2014-09-05 13:34:00 -0700197 if (lpNewFilePointer) {
bungeman@google.come25c6842011-08-17 14:53:54 +0000198 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
bungeman@google.com60157922011-08-13 00:06:17 +0000199 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000200 return hr;
201}
202
203HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
204 , DWORD grfStatFlag)
205{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000206 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000207 return STG_E_INVALIDFLAG;
208 }
halcanary96fcdcc2015-08-27 07:41:13 -0700209 pStatstg->pwcsName = nullptr;
scroggo@google.comb5571b32013-09-25 21:34:24 +0000210 // FIXME: Should not depend on getLength
211 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com9df621d2011-06-23 21:43:52 +0000212 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
213 pStatstg->clsid = CLSID_NULL;
214 pStatstg->type = STGTY_STREAM;
215 pStatstg->grfMode = STGM_READ;
216 return S_OK;
217}
218
219
220/**
221 * SkIWStream
222 */
223SkWIStream::SkWIStream(SkWStream* stream)
224 : SkBaseIStream()
225 , fSkWStream(stream)
226{ }
227
228SkWIStream::~SkWIStream() {
bsalomon49f085d2014-09-05 13:34:00 -0700229 if (this->fSkWStream) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000230 this->fSkWStream->flush();
231 }
232}
233
234HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
235 , IStream ** ppStream)
236{
237 *ppStream = new SkWIStream(stream);
238 return S_OK;
239}
240
241// ISequentialStream Interface
242HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
243 , ULONG cb
244 , ULONG* pcbWritten)
245{
246 HRESULT hr = S_OK;
247 bool wrote = this->fSkWStream->write(pv, cb);
248 if (wrote) {
249 *pcbWritten = cb;
250 } else {
251 *pcbWritten = 0;
252 hr = S_FALSE;
253 }
254 return hr;
255}
256
257// IStream Interface
bungeman@google.com14fc3212011-08-01 20:41:53 +0000258HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
259 this->fSkWStream->flush();
260 return S_OK;
261}
262
bungeman@google.com9df621d2011-06-23 21:43:52 +0000263HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
264 , DWORD grfStatFlag)
265{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000266 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000267 return STG_E_INVALIDFLAG;
268 }
halcanary96fcdcc2015-08-27 07:41:13 -0700269 pStatstg->pwcsName = nullptr;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000270 pStatstg->cbSize.QuadPart = 0;
271 pStatstg->clsid = CLSID_NULL;
272 pStatstg->type = STGTY_STREAM;
273 pStatstg->grfMode = STGM_WRITE;
274 return S_OK;
275}
mtklein1ee76512015-11-02 10:20:27 -0800276#endif//defined(SK_BUILD_FOR_WIN32)