• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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.
6  */
7 
8 #include "SkTypes.h"
9 #if defined(SK_BUILD_FOR_WIN32)
10 
11 #include "SkIStream.h"
12 #include "SkStream.h"
13 
14 /**
15  * SkBaseIStream
16  */
SkBaseIStream()17 SkBaseIStream::SkBaseIStream() : _refcount(1) { }
~SkBaseIStream()18 SkBaseIStream::~SkBaseIStream() { }
19 
QueryInterface(REFIID iid,void ** ppvObject)20 HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
21                                                       , void ** ppvObject)
22 {
23     if (nullptr == ppvObject) {
24         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 {
34         *ppvObject = nullptr;
35         return E_NOINTERFACE;
36     }
37 }
38 
AddRef(void)39 ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
40     return (ULONG)InterlockedIncrement(&_refcount);
41 }
42 
Release(void)43 ULONG 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
Read(void * pv,ULONG cb,ULONG * pcbRead)52 HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
53                                             , ULONG cb
54                                             , ULONG* pcbRead)
55 { return E_NOTIMPL; }
56 
Write(void const * pv,ULONG cb,ULONG * pcbWritten)57 HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
58                                              , ULONG cb
59                                              , ULONG* pcbWritten)
60 { return E_NOTIMPL; }
61 
62 // IStream Interface
SetSize(ULARGE_INTEGER)63 HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
64 { return E_NOTIMPL; }
65 
CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *)66 HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
67                                               , ULARGE_INTEGER
68                                               , ULARGE_INTEGER*
69                                               , ULARGE_INTEGER*)
70 { return E_NOTIMPL; }
71 
Commit(DWORD)72 HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
73 { return E_NOTIMPL; }
74 
Revert(void)75 HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
76 { return E_NOTIMPL; }
77 
LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD)78 HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
79                                                   , ULARGE_INTEGER
80                                                   , DWORD)
81 { return E_NOTIMPL; }
82 
UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD)83 HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
84                                                     , ULARGE_INTEGER
85                                                     , DWORD)
86 { return E_NOTIMPL; }
87 
Clone(IStream **)88 HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
89 { return E_NOTIMPL; }
90 
Seek(LARGE_INTEGER liDistanceToMove,DWORD dwOrigin,ULARGE_INTEGER * lpNewFilePointer)91 HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
92                                             , DWORD dwOrigin
93                                             , ULARGE_INTEGER* lpNewFilePointer)
94 { return E_NOTIMPL; }
95 
Stat(STATSTG * pStatstg,DWORD grfStatFlag)96 HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
97                                             , DWORD grfStatFlag)
98 { return E_NOTIMPL; }
99 
100 
101 /**
102  * SkIStream
103  */
SkIStream(SkStream * stream,bool deleteOnRelease)104 SkIStream::SkIStream(SkStream* stream, bool deleteOnRelease)
105     : SkBaseIStream()
106     , fSkStream(stream)
107     , fDeleteOnRelease(deleteOnRelease)
108     , fLocation()
109 {
110     this->fSkStream->rewind();
111 }
112 
~SkIStream()113 SkIStream::~SkIStream() {
114     if (fDeleteOnRelease) {
115         delete this->fSkStream;
116     }
117 }
118 
CreateFromSkStream(SkStream * stream,bool deleteOnRelease,IStream ** ppStream)119 HRESULT SkIStream::CreateFromSkStream(SkStream* stream
120                                     , bool deleteOnRelease
121                                     , IStream ** ppStream)
122 {
123     if (nullptr == stream) {
124         return E_INVALIDARG;
125     }
126     *ppStream = new SkIStream(stream, deleteOnRelease);
127     return S_OK;
128 }
129 
130 // ISequentialStream Interface
Read(void * pv,ULONG cb,ULONG * pcbRead)131 HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
132     *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
133     this->fLocation.QuadPart += *pcbRead;
134     return (*pcbRead == cb) ? S_OK : S_FALSE;
135 }
136 
Write(void const * pv,ULONG cb,ULONG * pcbWritten)137 HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
138                                          , ULONG cb
139                                          , ULONG* pcbWritten)
140 {
141     return STG_E_CANTSAVE;
142 }
143 
144 // IStream Interface
Seek(LARGE_INTEGER liDistanceToMove,DWORD dwOrigin,ULARGE_INTEGER * lpNewFilePointer)145 HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
146                                         , DWORD dwOrigin
147                                         , ULARGE_INTEGER* lpNewFilePointer)
148 {
149     HRESULT hr = S_OK;
150 
151     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(
157                 static_cast<size_t>(liDistanceToMove.QuadPart)
158             );
159             this->fLocation.QuadPart = skipped;
160             if (skipped != liDistanceToMove.QuadPart) {
161                 hr = E_FAIL;
162             }
163         }
164         break;
165     }
166     case STREAM_SEEK_CUR: {
167         size_t skipped = this->fSkStream->skip(
168             static_cast<size_t>(liDistanceToMove.QuadPart)
169         );
170         this->fLocation.QuadPart += skipped;
171         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 {
180             // FIXME: Should not depend on getLength.
181             // See https://code.google.com/p/skia/issues/detail?id=1570
182             LONGLONG skip = this->fSkStream->getLength()
183                           + liDistanceToMove.QuadPart;
184             size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
185             this->fLocation.QuadPart = skipped;
186             if (skipped != skip) {
187                 hr = E_FAIL;
188             }
189         }
190         break;
191     }
192     default:
193         hr = STG_E_INVALIDFUNCTION;
194         break;
195     }
196 
197     if (lpNewFilePointer) {
198         lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
199     }
200     return hr;
201 }
202 
Stat(STATSTG * pStatstg,DWORD grfStatFlag)203 HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
204                                         , DWORD grfStatFlag)
205 {
206     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
207         return STG_E_INVALIDFLAG;
208     }
209     pStatstg->pwcsName = nullptr;
210     // FIXME: Should not depend on getLength
211     // See https://code.google.com/p/skia/issues/detail?id=1570
212     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  */
SkWIStream(SkWStream * stream)223 SkWIStream::SkWIStream(SkWStream* stream)
224     : SkBaseIStream()
225     , fSkWStream(stream)
226 { }
227 
~SkWIStream()228 SkWIStream::~SkWIStream() {
229     if (this->fSkWStream) {
230         this->fSkWStream->flush();
231     }
232 }
233 
CreateFromSkWStream(SkWStream * stream,IStream ** ppStream)234 HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
235                                       , IStream ** ppStream)
236 {
237     *ppStream = new SkWIStream(stream);
238     return S_OK;
239 }
240 
241 // ISequentialStream Interface
Write(void const * pv,ULONG cb,ULONG * pcbWritten)242 HRESULT 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
Commit(DWORD)258 HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
259     this->fSkWStream->flush();
260     return S_OK;
261 }
262 
Stat(STATSTG * pStatstg,DWORD grfStatFlag)263 HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
264                                          , DWORD grfStatFlag)
265 {
266     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
267         return STG_E_INVALIDFLAG;
268     }
269     pStatstg->pwcsName = nullptr;
270     pStatstg->cbSize.QuadPart = 0;
271     pStatstg->clsid = CLSID_NULL;
272     pStatstg->type = STGTY_STREAM;
273     pStatstg->grfMode = STGM_WRITE;
274     return S_OK;
275 }
276 #endif//defined(SK_BUILD_FOR_WIN32)
277