123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkTypes.h"
- #if defined(SK_BUILD_FOR_WIN)
- #include "include/core/SkTypes.h"
- #include "include/private/SkTFitsIn.h"
- #include "include/private/SkTemplates.h"
- #include "src/utils/win/SkDWriteFontFileStream.h"
- #include "src/utils/win/SkHRESULT.h"
- #include "src/utils/win/SkTScopedComPtr.h"
- #include <dwrite.h>
- ///////////////////////////////////////////////////////////////////////////////
- // SkIDWriteFontFileStream
- SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
- : fFontFileStream(SkRefComPtr(fontFileStream))
- , fPos(0)
- , fLockedMemory(nullptr)
- , fFragmentLock(nullptr) {
- }
- SkDWriteFontFileStream::~SkDWriteFontFileStream() {
- if (fFragmentLock) {
- fFontFileStream->ReleaseFileFragment(fFragmentLock);
- }
- }
- size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
- HRESULT hr = S_OK;
- if (nullptr == buffer) {
- size_t fileSize = this->getLength();
- if (fPos + size > fileSize) {
- size_t skipped = fileSize - fPos;
- fPos = fileSize;
- return skipped;
- } else {
- fPos += size;
- return size;
- }
- }
- const void* start;
- void* fragmentLock;
- hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock);
- if (SUCCEEDED(hr)) {
- memcpy(buffer, start, size);
- fFontFileStream->ReleaseFileFragment(fragmentLock);
- fPos += size;
- return size;
- }
- //The read may have failed because we asked for too much data.
- size_t fileSize = this->getLength();
- if (fPos + size <= fileSize) {
- //This means we were within bounds, but failed for some other reason.
- return 0;
- }
- size_t read = fileSize - fPos;
- hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
- if (SUCCEEDED(hr)) {
- memcpy(buffer, start, read);
- fFontFileStream->ReleaseFileFragment(fragmentLock);
- fPos = fileSize;
- return read;
- }
- return 0;
- }
- bool SkDWriteFontFileStream::isAtEnd() const {
- return fPos == this->getLength();
- }
- bool SkDWriteFontFileStream::rewind() {
- fPos = 0;
- return true;
- }
- SkDWriteFontFileStream* SkDWriteFontFileStream::onDuplicate() const {
- return new SkDWriteFontFileStream(fFontFileStream.get());
- }
- size_t SkDWriteFontFileStream::getPosition() const {
- return fPos;
- }
- bool SkDWriteFontFileStream::seek(size_t position) {
- size_t length = this->getLength();
- fPos = (position > length) ? length : position;
- return true;
- }
- bool SkDWriteFontFileStream::move(long offset) {
- return seek(fPos + offset);
- }
- SkDWriteFontFileStream* SkDWriteFontFileStream::onFork() const {
- std::unique_ptr<SkDWriteFontFileStream> that(this->duplicate());
- that->seek(fPos);
- return that.release();
- }
- size_t SkDWriteFontFileStream::getLength() const {
- HRESULT hr = S_OK;
- UINT64 realFileSize = 0;
- hr = fFontFileStream->GetFileSize(&realFileSize);
- if (!SkTFitsIn<size_t>(realFileSize)) {
- return 0;
- }
- return static_cast<size_t>(realFileSize);
- }
- const void* SkDWriteFontFileStream::getMemoryBase() {
- if (fLockedMemory) {
- return fLockedMemory;
- }
- UINT64 fileSize;
- HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
- HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
- "Could not lock file fragment.");
- return fLockedMemory;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // SkIDWriteFontFileStreamWrapper
- HRESULT SkDWriteFontFileStreamWrapper::Create(SkStreamAsset* stream,
- SkDWriteFontFileStreamWrapper** streamFontFileStream)
- {
- *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream);
- if (nullptr == *streamFontFileStream) {
- return E_OUTOFMEMORY;
- }
- return S_OK;
- }
- SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStreamAsset* stream)
- : fRefCount(1), fStream(stream) {
- }
- HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
- *ppvObject = this;
- AddRef();
- return S_OK;
- } else {
- *ppvObject = nullptr;
- return E_NOINTERFACE;
- }
- }
- ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
- return InterlockedIncrement(&fRefCount);
- }
- ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
- ULONG newCount = InterlockedDecrement(&fRefCount);
- if (0 == newCount) {
- delete this;
- }
- return newCount;
- }
- HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
- void const** fragmentStart,
- UINT64 fileOffset,
- UINT64 fragmentSize,
- void** fragmentContext)
- {
- // The loader is responsible for doing a bounds check.
- UINT64 fileSize;
- this->GetFileSize(&fileSize);
- if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
- *fragmentStart = nullptr;
- *fragmentContext = nullptr;
- return E_FAIL;
- }
- if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) {
- return E_FAIL;
- }
- const void* data = fStream->getMemoryBase();
- if (data) {
- *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
- *fragmentContext = nullptr;
- } else {
- // May be called from multiple threads.
- SkAutoMutexExclusive ama(fStreamMutex);
- *fragmentStart = nullptr;
- *fragmentContext = nullptr;
- if (!fStream->seek(static_cast<size_t>(fileOffset))) {
- return E_FAIL;
- }
- SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
- if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
- return E_FAIL;
- }
- *fragmentStart = streamData.get();
- *fragmentContext = streamData.release();
- }
- return S_OK;
- }
- void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
- sk_free(fragmentContext);
- }
- HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
- *fileSize = fStream->getLength();
- return S_OK;
- }
- HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
- // The concept of last write time does not apply to this loader.
- *lastWriteTime = 0;
- return E_NOTIMPL;
- }
- #endif//defined(SK_BUILD_FOR_WIN)
|