1b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com/*
2b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com * Copyright 2012 Google Inc.
3b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com *
4b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com * Use of this source code is governed by a BSD-style license that can be
5b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com * found in the LICENSE file.
6b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com */
7b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
8b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com#include "SkTypes.h"
9b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com#include "SkDWriteFontFileStream.h"
10b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com#include "SkHRESULT.h"
11d9757a4413d194520d7b7cb8c1b9510cf4e30e17bungeman@google.com#include "SkTemplates.h"
12ffef84fbfa7c74332f6019a456dd47e01847de60bungeman@google.com#include "SkTFitsIn.h"
13f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com#include "SkTScopedComPtr.h"
14b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
15b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com#include <dwrite.h>
16b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
17b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com///////////////////////////////////////////////////////////////////////////////
18b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com//  SkIDWriteFontFileStream
19b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
20b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comSkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
21f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    : fFontFileStream(SkRefComPtr(fontFileStream))
22b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    , fPos(0)
23b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    , fLockedMemory(NULL)
24b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    , fFragmentLock(NULL) {
25b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
26b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
27b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comSkDWriteFontFileStream::~SkDWriteFontFileStream() {
28b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (fFragmentLock) {
29b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        fFontFileStream->ReleaseFileFragment(fFragmentLock);
30b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
31b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
32b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
33b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comsize_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
34b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    HRESULT hr = S_OK;
35b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
36b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (NULL == buffer) {
37f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        size_t fileSize = this->getLength();
38f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
39f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        if (fPos + size > fileSize) {
40f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com            size_t skipped = fileSize - fPos;
41f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com            fPos = fileSize;
42f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com            return skipped;
43b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        } else {
44f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com            fPos += size;
45f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com            return size;
46b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        }
47b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
48b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
49b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    const void* start;
50b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    void* fragmentLock;
51b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock);
52b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (SUCCEEDED(hr)) {
53b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        memcpy(buffer, start, size);
54b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        fFontFileStream->ReleaseFileFragment(fragmentLock);
55b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        fPos += size;
56b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return size;
57b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
58b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
59b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    //The read may have failed because we asked for too much data.
60f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    size_t fileSize = this->getLength();
61f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    if (fPos + size <= fileSize) {
62f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        //This means we were within bounds, but failed for some other reason.
63f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        return 0;
64f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    }
65f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
66f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    size_t read = fileSize - fPos;
67f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
68f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    if (SUCCEEDED(hr)) {
69f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        memcpy(buffer, start, read);
70f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        fFontFileStream->ReleaseFileFragment(fragmentLock);
71f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        fPos = fileSize;
72f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        return read;
73f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    }
74f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
75f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return 0;
76f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
77f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
78f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.combool SkDWriteFontFileStream::isAtEnd() const {
79f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return fPos == this->getLength();
80f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
81f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
82f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.combool SkDWriteFontFileStream::rewind() {
83f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    fPos = 0;
84f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return true;
85f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
86f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
87f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.comSkDWriteFontFileStream* SkDWriteFontFileStream::duplicate() const {
88f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return SkNEW_ARGS(SkDWriteFontFileStream, (fFontFileStream.get()));
89f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
90f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
91f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.comsize_t SkDWriteFontFileStream::getPosition() const {
92f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return fPos;
93f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
94f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
95f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.combool SkDWriteFontFileStream::seek(size_t position) {
96f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    size_t length = this->getLength();
97f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    fPos = (position > length) ? length : position;
98f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return true;
99f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
100f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
101f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.combool SkDWriteFontFileStream::move(long offset) {
102f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return seek(fPos + offset);
103f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
104f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
105f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.comSkDWriteFontFileStream* SkDWriteFontFileStream::fork() const {
106f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    SkAutoTUnref<SkDWriteFontFileStream> that(this->duplicate());
107f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    that->seek(fPos);
108f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return that.detach();
109f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
110f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
111f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.comsize_t SkDWriteFontFileStream::getLength() const {
112f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    HRESULT hr = S_OK;
113b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    UINT64 realFileSize = 0;
114b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    hr = fFontFileStream->GetFileSize(&realFileSize);
115d9757a4413d194520d7b7cb8c1b9510cf4e30e17bungeman@google.com    if (!SkTFitsIn<size_t>(realFileSize)) {
116b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return 0;
117b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
118f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return static_cast<size_t>(realFileSize);
119b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
120b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
121f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.comconst void* SkDWriteFontFileStream::getMemoryBase() {
122f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    if (fLockedMemory) {
123f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        return fLockedMemory;
124f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    }
125f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com
126f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    UINT64 fileSize;
127f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
128f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
129f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com         "Could not lock file fragment.");
130f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    return fLockedMemory;
131f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com}
132b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
133b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com///////////////////////////////////////////////////////////////////////////////
134b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com//  SkIDWriteFontFileStreamWrapper
135b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
136b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comHRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFileStreamWrapper** streamFontFileStream) {
137b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream);
138b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (NULL == streamFontFileStream) {
139b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return E_OUTOFMEMORY;
140b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
141b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    return S_OK;
142b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
143b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
144b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comSkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream)
145f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    : fRefCount(1), fStream(SkRef(stream)) {
146b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
147b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
148b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
149b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
150b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *ppvObject = this;
151b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        AddRef();
152b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return S_OK;
153b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    } else {
154b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *ppvObject = NULL;
155b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return E_NOINTERFACE;
156b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
157b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
158b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
159b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
160b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    return InterlockedIncrement(&fRefCount);
161b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
162b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
163b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
164b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    ULONG newCount = InterlockedDecrement(&fRefCount);
165b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (0 == newCount) {
166b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        delete this;
167b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
168b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    return newCount;
169b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
170b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
171b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
172b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    void const** fragmentStart,
173b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    UINT64 fileOffset,
174b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    UINT64 fragmentSize,
175b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    void** fragmentContext)
176b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com{
177b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    // The loader is responsible for doing a bounds check.
178b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    UINT64 fileSize;
179b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    this->GetFileSize(&fileSize);
180b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
181b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentStart = NULL;
182b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentContext = NULL;
183b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return E_FAIL;
184b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
185b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
186ffef84fbfa7c74332f6019a456dd47e01847de60bungeman@google.com    if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) {
187b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        return E_FAIL;
188b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
189b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
190b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    const void* data = fStream->getMemoryBase();
191b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    if (NULL != data) {
192b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
193b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentContext = NULL;
194b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
195b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    } else {
196b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        //May be called from multiple threads.
197b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        SkAutoMutexAcquire ama(fStreamMutex);
198b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
199b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentStart = NULL;
200b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentContext = NULL;
201b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
202b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        if (!fStream->rewind()) {
203b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com            return E_FAIL;
204b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        }
205b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
206b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com            return E_FAIL;
207b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        }
208f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com        SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
209b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
210b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com            return E_FAIL;
211b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        }
212b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
213b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentStart = streamData.get();
214b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com        *fragmentContext = streamData.detach();
215b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    }
216b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    return S_OK;
217b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
218b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
219b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comvoid STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
220f209ac2ecbb61b92348872f4642fa7f72103da2cbungeman@google.com    sk_free(fragmentContext);
221b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
222b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
223b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
224b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    *fileSize = fStream->getLength();
225b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    return S_OK;
226b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
227b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com
228b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.comHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
229b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    // The concept of last write time does not apply to this loader.
230b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    *lastWriteTime = 0;
231b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com    return E_NOTIMPL;
232b04d329bc9f0fb577d5b954edad7ac41fc721c6abungeman@google.com}
233