• 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 "include/core/SkTypes.h"
9 #if defined(SK_BUILD_FOR_WIN)
10 
11 #include "include/core/SkStream.h"
12 #include "src/utils/win/SkIStream.h"
13 
14 /**
15  * SkBaseIStream
16  */
SkBaseIStream()17 SkBaseIStream::SkBaseIStream() : _refcount(1) { }
~SkBaseIStream()18 SkBaseIStream::~SkBaseIStream() { }
19 
QueryInterface(REFIID iid,void ** ppvObject)20 SK_STDMETHODIMP SkBaseIStream::QueryInterface(REFIID iid, void ** ppvObject) {
21     if (nullptr == ppvObject) {
22         return E_INVALIDARG;
23     }
24     if (iid == __uuidof(IUnknown)
25         || iid == __uuidof(IStream)
26         || iid == __uuidof(ISequentialStream))
27     {
28         *ppvObject = static_cast<IStream*>(this);
29         AddRef();
30         return S_OK;
31     } else {
32         *ppvObject = nullptr;
33         return E_NOINTERFACE;
34     }
35 }
36 
SK_STDMETHODIMP_(ULONG)37 SK_STDMETHODIMP_(ULONG) SkBaseIStream::AddRef() {
38     return (ULONG)InterlockedIncrement(&_refcount);
39 }
40 
SK_STDMETHODIMP_(ULONG)41 SK_STDMETHODIMP_(ULONG) SkBaseIStream::Release() {
42     ULONG res = (ULONG) InterlockedDecrement(&_refcount);
43     if (0 == res) {
44         delete this;
45     }
46     return res;
47 }
48 
49 // ISequentialStream Interface
Read(void * pv,ULONG cb,ULONG * pcbRead)50 SK_STDMETHODIMP SkBaseIStream::Read(void* pv, ULONG cb, ULONG* pcbRead)
51 { return E_NOTIMPL; }
52 
Write(void const * pv,ULONG cb,ULONG * pcbWritten)53 SK_STDMETHODIMP SkBaseIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten)
54 { return E_NOTIMPL; }
55 
56 // IStream Interface
SetSize(ULARGE_INTEGER)57 SK_STDMETHODIMP SkBaseIStream::SetSize(ULARGE_INTEGER)
58 { return E_NOTIMPL; }
59 
CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *)60 SK_STDMETHODIMP SkBaseIStream::CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*)
61 { return E_NOTIMPL; }
62 
Commit(DWORD)63 SK_STDMETHODIMP SkBaseIStream::Commit(DWORD)
64 { return E_NOTIMPL; }
65 
Revert()66 SK_STDMETHODIMP SkBaseIStream::Revert()
67 { return E_NOTIMPL; }
68 
LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD)69 SK_STDMETHODIMP SkBaseIStream::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
70 { return E_NOTIMPL; }
71 
UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD)72 SK_STDMETHODIMP SkBaseIStream::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
73 { return E_NOTIMPL; }
74 
Clone(IStream **)75 SK_STDMETHODIMP SkBaseIStream::Clone(IStream**)
76 { return E_NOTIMPL; }
77 
Seek(LARGE_INTEGER liDistanceToMove,DWORD dwOrigin,ULARGE_INTEGER * lpNewFilePointer)78 SK_STDMETHODIMP SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove,
79                                     DWORD dwOrigin,
80                                     ULARGE_INTEGER* lpNewFilePointer)
81 { return E_NOTIMPL; }
82 
Stat(STATSTG * pStatstg,DWORD grfStatFlag)83 SK_STDMETHODIMP SkBaseIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag)
84 { return E_NOTIMPL; }
85 
86 
87 /**
88  * SkIStream
89  */
SkIStream(SkStream * stream,bool deleteOnRelease)90 SkIStream::SkIStream(SkStream* stream, bool deleteOnRelease)
91     : SkBaseIStream()
92     , fSkStream(stream)
93     , fDeleteOnRelease(deleteOnRelease)
94     , fLocation()
95 {
96     this->fSkStream->rewind();
97 }
98 
~SkIStream()99 SkIStream::~SkIStream() {
100     if (fDeleteOnRelease) {
101         delete this->fSkStream;
102     }
103 }
104 
CreateFromSkStream(SkStream * stream,bool deleteOnRelease,IStream ** ppStream)105 HRESULT SkIStream::CreateFromSkStream(SkStream* stream, bool deleteOnRelease, IStream ** ppStream) {
106     if (nullptr == stream) {
107         return E_INVALIDARG;
108     }
109     *ppStream = new SkIStream(stream, deleteOnRelease);
110     return S_OK;
111 }
112 
113 // ISequentialStream Interface
Read(void * pv,ULONG cb,ULONG * pcbRead)114 SK_STDMETHODIMP SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
115     *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
116     this->fLocation.QuadPart += *pcbRead;
117     return (*pcbRead == cb) ? S_OK : S_FALSE;
118 }
119 
Write(void const * pv,ULONG cb,ULONG * pcbWritten)120 SK_STDMETHODIMP SkIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
121     return STG_E_CANTSAVE;
122 }
123 
124 // IStream Interface
Seek(LARGE_INTEGER liDistanceToMove,DWORD dwOrigin,ULARGE_INTEGER * lpNewFilePointer)125 SK_STDMETHODIMP SkIStream::Seek(LARGE_INTEGER liDistanceToMove,
126                                 DWORD dwOrigin,
127                                 ULARGE_INTEGER* lpNewFilePointer)
128 {
129     HRESULT hr = S_OK;
130 
131     switch(dwOrigin) {
132     case STREAM_SEEK_SET: {
133         if (!this->fSkStream->rewind()) {
134             hr = E_FAIL;
135         } else {
136             size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart);
137             size_t skipped = this->fSkStream->skip(skip);
138             this->fLocation.QuadPart = skipped;
139             if (skipped != skip) {
140                 hr = E_FAIL;
141             }
142         }
143         break;
144     }
145     case STREAM_SEEK_CUR: {
146         size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart);
147         size_t skipped = this->fSkStream->skip(skip);
148         this->fLocation.QuadPart += skipped;
149         if (skipped != skip) {
150             hr = E_FAIL;
151         }
152         break;
153     }
154     case STREAM_SEEK_END: {
155         if (!this->fSkStream->rewind()) {
156             hr = E_FAIL;
157         } else {
158             // FIXME: Should not depend on getLength.
159             // See https://code.google.com/p/skia/issues/detail?id=1570
160             size_t skip = static_cast<size_t>(this->fSkStream->getLength() +
161                                               liDistanceToMove.QuadPart);
162             size_t skipped = this->fSkStream->skip(skip);
163             this->fLocation.QuadPart = skipped;
164             if (skipped != skip) {
165                 hr = E_FAIL;
166             }
167         }
168         break;
169     }
170     default:
171         hr = STG_E_INVALIDFUNCTION;
172         break;
173     }
174 
175     if (lpNewFilePointer) {
176         lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
177     }
178     return hr;
179 }
180 
Stat(STATSTG * pStatstg,DWORD grfStatFlag)181 SK_STDMETHODIMP SkIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
182     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
183         return STG_E_INVALIDFLAG;
184     }
185     pStatstg->pwcsName = nullptr;
186     // FIXME: Should not depend on getLength
187     // See https://code.google.com/p/skia/issues/detail?id=1570
188     pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
189     pStatstg->clsid = CLSID_NULL;
190     pStatstg->type = STGTY_STREAM;
191     pStatstg->grfMode = STGM_READ;
192     return S_OK;
193 }
194 
195 
196 /**
197  * SkIWStream
198  */
SkWIStream(SkWStream * stream)199 SkWIStream::SkWIStream(SkWStream* stream)
200     : SkBaseIStream()
201     , fSkWStream(stream)
202 { }
203 
~SkWIStream()204 SkWIStream::~SkWIStream() {
205     if (this->fSkWStream) {
206         this->fSkWStream->flush();
207     }
208 }
209 
CreateFromSkWStream(SkWStream * stream,IStream ** ppStream)210 HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream, IStream ** ppStream) {
211     *ppStream = new SkWIStream(stream);
212     return S_OK;
213 }
214 
215 // ISequentialStream Interface
Write(void const * pv,ULONG cb,ULONG * pcbWritten)216 SK_STDMETHODIMP SkWIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
217     HRESULT hr = S_OK;
218     bool wrote = this->fSkWStream->write(pv, cb);
219     if (wrote) {
220         *pcbWritten = cb;
221     } else {
222         *pcbWritten = 0;
223         hr = S_FALSE;
224     }
225     return hr;
226 }
227 
228 // IStream Interface
Commit(DWORD)229 SK_STDMETHODIMP SkWIStream::Commit(DWORD) {
230     this->fSkWStream->flush();
231     return S_OK;
232 }
233 
Stat(STATSTG * pStatstg,DWORD grfStatFlag)234 SK_STDMETHODIMP SkWIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
235     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
236         return STG_E_INVALIDFLAG;
237     }
238     pStatstg->pwcsName = nullptr;
239     pStatstg->cbSize.QuadPart = 0;
240     pStatstg->clsid = CLSID_NULL;
241     pStatstg->type = STGTY_STREAM;
242     pStatstg->grfMode = STGM_WRITE;
243     return S_OK;
244 }
245 #endif//defined(SK_BUILD_FOR_WIN)
246