SkDWriteFontFileStream.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright 2012 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/SkTypes.h"
  10. #include "include/private/SkTFitsIn.h"
  11. #include "include/private/SkTemplates.h"
  12. #include "src/utils/win/SkDWriteFontFileStream.h"
  13. #include "src/utils/win/SkHRESULT.h"
  14. #include "src/utils/win/SkTScopedComPtr.h"
  15. #include <dwrite.h>
  16. ///////////////////////////////////////////////////////////////////////////////
  17. // SkIDWriteFontFileStream
  18. SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
  19. : fFontFileStream(SkRefComPtr(fontFileStream))
  20. , fPos(0)
  21. , fLockedMemory(nullptr)
  22. , fFragmentLock(nullptr) {
  23. }
  24. SkDWriteFontFileStream::~SkDWriteFontFileStream() {
  25. if (fFragmentLock) {
  26. fFontFileStream->ReleaseFileFragment(fFragmentLock);
  27. }
  28. }
  29. size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
  30. HRESULT hr = S_OK;
  31. if (nullptr == buffer) {
  32. size_t fileSize = this->getLength();
  33. if (fPos + size > fileSize) {
  34. size_t skipped = fileSize - fPos;
  35. fPos = fileSize;
  36. return skipped;
  37. } else {
  38. fPos += size;
  39. return size;
  40. }
  41. }
  42. const void* start;
  43. void* fragmentLock;
  44. hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock);
  45. if (SUCCEEDED(hr)) {
  46. memcpy(buffer, start, size);
  47. fFontFileStream->ReleaseFileFragment(fragmentLock);
  48. fPos += size;
  49. return size;
  50. }
  51. //The read may have failed because we asked for too much data.
  52. size_t fileSize = this->getLength();
  53. if (fPos + size <= fileSize) {
  54. //This means we were within bounds, but failed for some other reason.
  55. return 0;
  56. }
  57. size_t read = fileSize - fPos;
  58. hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
  59. if (SUCCEEDED(hr)) {
  60. memcpy(buffer, start, read);
  61. fFontFileStream->ReleaseFileFragment(fragmentLock);
  62. fPos = fileSize;
  63. return read;
  64. }
  65. return 0;
  66. }
  67. bool SkDWriteFontFileStream::isAtEnd() const {
  68. return fPos == this->getLength();
  69. }
  70. bool SkDWriteFontFileStream::rewind() {
  71. fPos = 0;
  72. return true;
  73. }
  74. SkDWriteFontFileStream* SkDWriteFontFileStream::onDuplicate() const {
  75. return new SkDWriteFontFileStream(fFontFileStream.get());
  76. }
  77. size_t SkDWriteFontFileStream::getPosition() const {
  78. return fPos;
  79. }
  80. bool SkDWriteFontFileStream::seek(size_t position) {
  81. size_t length = this->getLength();
  82. fPos = (position > length) ? length : position;
  83. return true;
  84. }
  85. bool SkDWriteFontFileStream::move(long offset) {
  86. return seek(fPos + offset);
  87. }
  88. SkDWriteFontFileStream* SkDWriteFontFileStream::onFork() const {
  89. std::unique_ptr<SkDWriteFontFileStream> that(this->duplicate());
  90. that->seek(fPos);
  91. return that.release();
  92. }
  93. size_t SkDWriteFontFileStream::getLength() const {
  94. HRESULT hr = S_OK;
  95. UINT64 realFileSize = 0;
  96. hr = fFontFileStream->GetFileSize(&realFileSize);
  97. if (!SkTFitsIn<size_t>(realFileSize)) {
  98. return 0;
  99. }
  100. return static_cast<size_t>(realFileSize);
  101. }
  102. const void* SkDWriteFontFileStream::getMemoryBase() {
  103. if (fLockedMemory) {
  104. return fLockedMemory;
  105. }
  106. UINT64 fileSize;
  107. HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
  108. HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
  109. "Could not lock file fragment.");
  110. return fLockedMemory;
  111. }
  112. ///////////////////////////////////////////////////////////////////////////////
  113. // SkIDWriteFontFileStreamWrapper
  114. HRESULT SkDWriteFontFileStreamWrapper::Create(SkStreamAsset* stream,
  115. SkDWriteFontFileStreamWrapper** streamFontFileStream)
  116. {
  117. *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream);
  118. if (nullptr == *streamFontFileStream) {
  119. return E_OUTOFMEMORY;
  120. }
  121. return S_OK;
  122. }
  123. SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStreamAsset* stream)
  124. : fRefCount(1), fStream(stream) {
  125. }
  126. HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
  127. if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
  128. *ppvObject = this;
  129. AddRef();
  130. return S_OK;
  131. } else {
  132. *ppvObject = nullptr;
  133. return E_NOINTERFACE;
  134. }
  135. }
  136. ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
  137. return InterlockedIncrement(&fRefCount);
  138. }
  139. ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
  140. ULONG newCount = InterlockedDecrement(&fRefCount);
  141. if (0 == newCount) {
  142. delete this;
  143. }
  144. return newCount;
  145. }
  146. HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
  147. void const** fragmentStart,
  148. UINT64 fileOffset,
  149. UINT64 fragmentSize,
  150. void** fragmentContext)
  151. {
  152. // The loader is responsible for doing a bounds check.
  153. UINT64 fileSize;
  154. this->GetFileSize(&fileSize);
  155. if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
  156. *fragmentStart = nullptr;
  157. *fragmentContext = nullptr;
  158. return E_FAIL;
  159. }
  160. if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) {
  161. return E_FAIL;
  162. }
  163. const void* data = fStream->getMemoryBase();
  164. if (data) {
  165. *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
  166. *fragmentContext = nullptr;
  167. } else {
  168. // May be called from multiple threads.
  169. SkAutoMutexExclusive ama(fStreamMutex);
  170. *fragmentStart = nullptr;
  171. *fragmentContext = nullptr;
  172. if (!fStream->seek(static_cast<size_t>(fileOffset))) {
  173. return E_FAIL;
  174. }
  175. SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
  176. if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
  177. return E_FAIL;
  178. }
  179. *fragmentStart = streamData.get();
  180. *fragmentContext = streamData.release();
  181. }
  182. return S_OK;
  183. }
  184. void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
  185. sk_free(fragmentContext);
  186. }
  187. HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
  188. *fileSize = fStream->getLength();
  189. return S_OK;
  190. }
  191. HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
  192. // The concept of last write time does not apply to this loader.
  193. *lastWriteTime = 0;
  194. return E_NOTIMPL;
  195. }
  196. #endif//defined(SK_BUILD_FOR_WIN)