1e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/* 2e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * Copyright 2012 Google Inc. 3e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * 4e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * Use of this source code is governed by a BSD-style license that can be 5e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * found in the LICENSE file. 6e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com */ 7e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 8e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkTypes.h" 9e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkDWriteFontFileStream.h" 10e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkHRESULT.h" 1111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com#include "SkTemplates.h" 12f5cc5b140c1c00c536e02b5cfbe158bb2d5c2c15bungeman@google.com#include "SkTFitsIn.h" 136cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com#include "SkTScopedComPtr.h" 14e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 15e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include <dwrite.h> 16e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 17e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/////////////////////////////////////////////////////////////////////////////// 18e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com// SkIDWriteFontFileStream 19e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 20e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comSkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream) 216cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com : fFontFileStream(SkRefComPtr(fontFileStream)) 22e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com , fPos(0) 23e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com , fLockedMemory(NULL) 24e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com , fFragmentLock(NULL) { 25e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 26e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 27e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comSkDWriteFontFileStream::~SkDWriteFontFileStream() { 28e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (fFragmentLock) { 29e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fFontFileStream->ReleaseFileFragment(fFragmentLock); 30e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 31e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 32e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 33e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comsize_t SkDWriteFontFileStream::read(void* buffer, size_t size) { 34e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com HRESULT hr = S_OK; 35e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 36e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (NULL == buffer) { 376cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t fileSize = this->getLength(); 386cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 396cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (fPos + size > fileSize) { 406cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t skipped = fileSize - fPos; 416cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com fPos = fileSize; 426cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return skipped; 43e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 446cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com fPos += size; 456cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return size; 46e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 47e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 48e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 49e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const void* start; 50e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com void* fragmentLock; 51e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock); 52e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (SUCCEEDED(hr)) { 53e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com memcpy(buffer, start, size); 54e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fFontFileStream->ReleaseFileFragment(fragmentLock); 55e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fPos += size; 56e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return size; 57e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 58e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 59e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //The read may have failed because we asked for too much data. 606cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t fileSize = this->getLength(); 616cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (fPos + size <= fileSize) { 626cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //This means we were within bounds, but failed for some other reason. 636cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return 0; 646cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 656cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 666cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t read = fileSize - fPos; 676cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock); 686cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (SUCCEEDED(hr)) { 696cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com memcpy(buffer, start, read); 706cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com fFontFileStream->ReleaseFileFragment(fragmentLock); 716cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com fPos = fileSize; 726cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return read; 736cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 746cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 756cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return 0; 766cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 776cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 786cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkDWriteFontFileStream::isAtEnd() const { 796cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return fPos == this->getLength(); 806cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 816cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 826cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkDWriteFontFileStream::rewind() { 836cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com fPos = 0; 846cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return true; 856cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 866cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 876cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkDWriteFontFileStream* SkDWriteFontFileStream::duplicate() const { 886cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return SkNEW_ARGS(SkDWriteFontFileStream, (fFontFileStream.get())); 896cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 906cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 916cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkDWriteFontFileStream::getPosition() const { 926cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return fPos; 936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 946cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 956cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkDWriteFontFileStream::seek(size_t position) { 966cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t length = this->getLength(); 976cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com fPos = (position > length) ? length : position; 986cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return true; 996cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 1006cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 1016cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkDWriteFontFileStream::move(long offset) { 1026cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return seek(fPos + offset); 1036cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 1046cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 1056cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkDWriteFontFileStream* SkDWriteFontFileStream::fork() const { 1066cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkAutoTUnref<SkDWriteFontFileStream> that(this->duplicate()); 1076cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com that->seek(fPos); 1086cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return that.detach(); 1096cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 1106cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 1116cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkDWriteFontFileStream::getLength() const { 1126cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com HRESULT hr = S_OK; 113e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com UINT64 realFileSize = 0; 114e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com hr = fFontFileStream->GetFileSize(&realFileSize); 11511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (!SkTFitsIn<size_t>(realFileSize)) { 116e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return 0; 117e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 1186cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return static_cast<size_t>(realFileSize); 119e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 120e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 1216cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comconst void* SkDWriteFontFileStream::getMemoryBase() { 1226cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (fLockedMemory) { 1236cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return fLockedMemory; 1246cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 1256cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 1266cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com UINT64 fileSize; 1276cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size"); 1286cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock), 1296cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com "Could not lock file fragment."); 1306cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return fLockedMemory; 1316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 132e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 133e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/////////////////////////////////////////////////////////////////////////////// 134e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com// SkIDWriteFontFileStreamWrapper 135e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 136e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comHRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFileStreamWrapper** streamFontFileStream) { 137e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream); 138e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (NULL == streamFontFileStream) { 139e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_OUTOFMEMORY; 140e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 141e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return S_OK; 142e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 143e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 144e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comSkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream) 1456cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com : fRefCount(1), fStream(SkRef(stream)) { 146e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 147e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 148e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) { 149e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) { 150e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *ppvObject = this; 151e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com AddRef(); 152e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return S_OK; 153e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 154e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *ppvObject = NULL; 155e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_NOINTERFACE; 156e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 157e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 158e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 159e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() { 160e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return InterlockedIncrement(&fRefCount); 161e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 162e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 163e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() { 164e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com ULONG newCount = InterlockedDecrement(&fRefCount); 165e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (0 == newCount) { 166e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com delete this; 167e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 168e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return newCount; 169e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 170e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 171e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment( 172e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com void const** fragmentStart, 173e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com UINT64 fileOffset, 174e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com UINT64 fragmentSize, 175e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com void** fragmentContext) 176e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com{ 177e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com // The loader is responsible for doing a bounds check. 178e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com UINT64 fileSize; 179e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com this->GetFileSize(&fileSize); 180e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) { 181e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentStart = NULL; 182e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentContext = NULL; 183e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_FAIL; 184e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 185e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 186f5cc5b140c1c00c536e02b5cfbe158bb2d5c2c15bungeman@google.com if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) { 187e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_FAIL; 188e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 189e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 190e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const void* data = fStream->getMemoryBase(); 19149f085dddff10473b6ebf832a974288300224e60bsalomon if (data) { 192e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset); 193e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentContext = NULL; 194e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 195e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 196e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //May be called from multiple threads. 197e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkAutoMutexAcquire ama(fStreamMutex); 198e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 199e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentStart = NULL; 200e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentContext = NULL; 201e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 202e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (!fStream->rewind()) { 203e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_FAIL; 204e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 205e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) { 206e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_FAIL; 207e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 2086cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize)); 209e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) { 210e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_FAIL; 211e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 212e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 213e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentStart = streamData.get(); 214e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fragmentContext = streamData.detach(); 215e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 216e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return S_OK; 217e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 218e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 219e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comvoid STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) { 2206cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com sk_free(fragmentContext); 221e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 222e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 223e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) { 224e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *fileSize = fStream->getLength(); 225e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return S_OK; 226e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 227e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 228e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) { 229e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com // The concept of last write time does not apply to this loader. 230e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *lastWriteTime = 0; 231e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return E_NOTIMPL; 232e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 233