180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDWriteFontFileStream.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkHRESULT.h"
1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkTemplates.h"
1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkTFitsIn.h"
1358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkTScopedComPtr.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <dwrite.h>
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  SkIDWriteFontFileStream
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    : fFontFileStream(SkRefComPtr(fontFileStream))
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fPos(0)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fLockedMemory(NULL)
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fFragmentLock(NULL) {
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDWriteFontFileStream::~SkDWriteFontFileStream() {
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fFragmentLock) {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fFontFileStream->ReleaseFileFragment(fFragmentLock);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    HRESULT hr = S_OK;
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == buffer) {
3758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        size_t fileSize = this->getLength();
3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (fPos + size > fileSize) {
4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            size_t skipped = fileSize - fPos;
4158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            fPos = fileSize;
4258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return skipped;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            fPos += size;
4558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return size;
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const void* start;
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* fragmentLock;
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SUCCEEDED(hr)) {
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(buffer, start, size);
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fFontFileStream->ReleaseFileFragment(fragmentLock);
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPos += size;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return size;
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //The read may have failed because we asked for too much data.
6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size_t fileSize = this->getLength();
6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (fPos + size <= fileSize) {
6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        //This means we were within bounds, but failed for some other reason.
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size_t read = fileSize - fPos;
6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (SUCCEEDED(hr)) {
6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        memcpy(buffer, start, read);
7058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        fFontFileStream->ReleaseFileFragment(fragmentLock);
7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        fPos = fileSize;
7258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return read;
7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
7558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return 0;
7658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkDWriteFontFileStream::isAtEnd() const {
7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return fPos == this->getLength();
8058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
8158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
8258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkDWriteFontFileStream::rewind() {
8358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fPos = 0;
8458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return true;
8558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
8758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkDWriteFontFileStream* SkDWriteFontFileStream::duplicate() const {
8858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkNEW_ARGS(SkDWriteFontFileStream, (fFontFileStream.get()));
8958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
9058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergersize_t SkDWriteFontFileStream::getPosition() const {
9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return fPos;
9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkDWriteFontFileStream::seek(size_t position) {
9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size_t length = this->getLength();
9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fPos = (position > length) ? length : position;
9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return true;
9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkDWriteFontFileStream::move(long offset) {
10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return seek(fPos + offset);
10358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
10458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
10558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkDWriteFontFileStream* SkDWriteFontFileStream::fork() const {
10658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkAutoTUnref<SkDWriteFontFileStream> that(this->duplicate());
10758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    that->seek(fPos);
10858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return that.detach();
10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
11058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
11158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergersize_t SkDWriteFontFileStream::getLength() const {
11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    HRESULT hr = S_OK;
11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    UINT64 realFileSize = 0;
11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    hr = fFontFileStream->GetFileSize(&realFileSize);
11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!SkTFitsIn<size_t>(realFileSize)) {
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return static_cast<size_t>(realFileSize);
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerconst void* SkDWriteFontFileStream::getMemoryBase() {
12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (fLockedMemory) {
12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return fLockedMemory;
12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    UINT64 fileSize;
12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger         "Could not lock file fragment.");
13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return fLockedMemory;
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  SkIDWriteFontFileStreamWrapper
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFileStreamWrapper** streamFontFileStream) {
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream);
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == streamFontFileStream) {
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return E_OUTOFMEMORY;
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return S_OK;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream)
14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    : fRefCount(1), fStream(SkRef(stream)) {
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *ppvObject = this;
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        AddRef();
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return S_OK;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *ppvObject = NULL;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return E_NOINTERFACE;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return InterlockedIncrement(&fRefCount);
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ULONG newCount = InterlockedDecrement(&fRefCount);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == newCount) {
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete this;
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return newCount;
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void const** fragmentStart,
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UINT64 fileOffset,
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UINT64 fragmentSize,
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void** fragmentContext)
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The loader is responsible for doing a bounds check.
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UINT64 fileSize;
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->GetFileSize(&fileSize);
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentStart = NULL;
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentContext = NULL;
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return E_FAIL;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return E_FAIL;
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const void* data = fStream->getMemoryBase();
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != data) {
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentContext = NULL;
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        //May be called from multiple threads.
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAutoMutexAcquire ama(fStreamMutex);
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentStart = NULL;
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentContext = NULL;
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!fStream->rewind()) {
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return E_FAIL;
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return E_FAIL;
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
20858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return E_FAIL;
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentStart = streamData.get();
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fragmentContext = streamData.detach();
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return S_OK;
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
22058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    sk_free(fragmentContext);
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fileSize = fStream->getLength();
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return S_OK;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The concept of last write time does not apply to this loader.
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *lastWriteTime = 0;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return E_NOTIMPL;
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
233