SkIStream.cpp 7.7 KB

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