gfx/skia/trunk/src/utils/win/SkDWriteFontFileStream.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/utils/win/SkDWriteFontFileStream.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,232 @@
     1.4 +/*
     1.5 + * Copyright 2012 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#include "SkTypes.h"
    1.12 +#include "SkDWriteFontFileStream.h"
    1.13 +#include "SkHRESULT.h"
    1.14 +#include "SkTemplates.h"
    1.15 +#include "SkTFitsIn.h"
    1.16 +#include "SkTScopedComPtr.h"
    1.17 +
    1.18 +#include <dwrite.h>
    1.19 +
    1.20 +///////////////////////////////////////////////////////////////////////////////
    1.21 +//  SkIDWriteFontFileStream
    1.22 +
    1.23 +SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
    1.24 +    : fFontFileStream(SkRefComPtr(fontFileStream))
    1.25 +    , fPos(0)
    1.26 +    , fLockedMemory(NULL)
    1.27 +    , fFragmentLock(NULL) {
    1.28 +}
    1.29 +
    1.30 +SkDWriteFontFileStream::~SkDWriteFontFileStream() {
    1.31 +    if (fFragmentLock) {
    1.32 +        fFontFileStream->ReleaseFileFragment(fFragmentLock);
    1.33 +    }
    1.34 +}
    1.35 +
    1.36 +size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
    1.37 +    HRESULT hr = S_OK;
    1.38 +
    1.39 +    if (NULL == buffer) {
    1.40 +        size_t fileSize = this->getLength();
    1.41 +
    1.42 +        if (fPos + size > fileSize) {
    1.43 +            size_t skipped = fileSize - fPos;
    1.44 +            fPos = fileSize;
    1.45 +            return skipped;
    1.46 +        } else {
    1.47 +            fPos += size;
    1.48 +            return size;
    1.49 +        }
    1.50 +    }
    1.51 +
    1.52 +    const void* start;
    1.53 +    void* fragmentLock;
    1.54 +    hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock);
    1.55 +    if (SUCCEEDED(hr)) {
    1.56 +        memcpy(buffer, start, size);
    1.57 +        fFontFileStream->ReleaseFileFragment(fragmentLock);
    1.58 +        fPos += size;
    1.59 +        return size;
    1.60 +    }
    1.61 +
    1.62 +    //The read may have failed because we asked for too much data.
    1.63 +    size_t fileSize = this->getLength();
    1.64 +    if (fPos + size <= fileSize) {
    1.65 +        //This means we were within bounds, but failed for some other reason.
    1.66 +        return 0;
    1.67 +    }
    1.68 +
    1.69 +    size_t read = fileSize - fPos;
    1.70 +    hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
    1.71 +    if (SUCCEEDED(hr)) {
    1.72 +        memcpy(buffer, start, read);
    1.73 +        fFontFileStream->ReleaseFileFragment(fragmentLock);
    1.74 +        fPos = fileSize;
    1.75 +        return read;
    1.76 +    }
    1.77 +
    1.78 +    return 0;
    1.79 +}
    1.80 +
    1.81 +bool SkDWriteFontFileStream::isAtEnd() const {
    1.82 +    return fPos == this->getLength();
    1.83 +}
    1.84 +
    1.85 +bool SkDWriteFontFileStream::rewind() {
    1.86 +    fPos = 0;
    1.87 +    return true;
    1.88 +}
    1.89 +
    1.90 +SkDWriteFontFileStream* SkDWriteFontFileStream::duplicate() const {
    1.91 +    return SkNEW_ARGS(SkDWriteFontFileStream, (fFontFileStream.get()));
    1.92 +}
    1.93 +
    1.94 +size_t SkDWriteFontFileStream::getPosition() const {
    1.95 +    return fPos;
    1.96 +}
    1.97 +
    1.98 +bool SkDWriteFontFileStream::seek(size_t position) {
    1.99 +    size_t length = this->getLength();
   1.100 +    fPos = (position > length) ? length : position;
   1.101 +    return true;
   1.102 +}
   1.103 +
   1.104 +bool SkDWriteFontFileStream::move(long offset) {
   1.105 +    return seek(fPos + offset);
   1.106 +}
   1.107 +
   1.108 +SkDWriteFontFileStream* SkDWriteFontFileStream::fork() const {
   1.109 +    SkAutoTUnref<SkDWriteFontFileStream> that(this->duplicate());
   1.110 +    that->seek(fPos);
   1.111 +    return that.detach();
   1.112 +}
   1.113 +
   1.114 +size_t SkDWriteFontFileStream::getLength() const {
   1.115 +    HRESULT hr = S_OK;
   1.116 +    UINT64 realFileSize = 0;
   1.117 +    hr = fFontFileStream->GetFileSize(&realFileSize);
   1.118 +    if (!SkTFitsIn<size_t>(realFileSize)) {
   1.119 +        return 0;
   1.120 +    }
   1.121 +    return static_cast<size_t>(realFileSize);
   1.122 +}
   1.123 +
   1.124 +const void* SkDWriteFontFileStream::getMemoryBase() {
   1.125 +    if (fLockedMemory) {
   1.126 +        return fLockedMemory;
   1.127 +    }
   1.128 +
   1.129 +    UINT64 fileSize;
   1.130 +    HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
   1.131 +    HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
   1.132 +         "Could not lock file fragment.");
   1.133 +    return fLockedMemory;
   1.134 +}
   1.135 +
   1.136 +///////////////////////////////////////////////////////////////////////////////
   1.137 +//  SkIDWriteFontFileStreamWrapper
   1.138 +
   1.139 +HRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFileStreamWrapper** streamFontFileStream) {
   1.140 +    *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream);
   1.141 +    if (NULL == streamFontFileStream) {
   1.142 +        return E_OUTOFMEMORY;
   1.143 +    }
   1.144 +    return S_OK;
   1.145 +}
   1.146 +
   1.147 +SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream)
   1.148 +    : fRefCount(1), fStream(SkRef(stream)) {
   1.149 +}
   1.150 +
   1.151 +HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
   1.152 +    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
   1.153 +        *ppvObject = this;
   1.154 +        AddRef();
   1.155 +        return S_OK;
   1.156 +    } else {
   1.157 +        *ppvObject = NULL;
   1.158 +        return E_NOINTERFACE;
   1.159 +    }
   1.160 +}
   1.161 +
   1.162 +ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
   1.163 +    return InterlockedIncrement(&fRefCount);
   1.164 +}
   1.165 +
   1.166 +ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
   1.167 +    ULONG newCount = InterlockedDecrement(&fRefCount);
   1.168 +    if (0 == newCount) {
   1.169 +        delete this;
   1.170 +    }
   1.171 +    return newCount;
   1.172 +}
   1.173 +
   1.174 +HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
   1.175 +    void const** fragmentStart,
   1.176 +    UINT64 fileOffset,
   1.177 +    UINT64 fragmentSize,
   1.178 +    void** fragmentContext)
   1.179 +{
   1.180 +    // The loader is responsible for doing a bounds check.
   1.181 +    UINT64 fileSize;
   1.182 +    this->GetFileSize(&fileSize);
   1.183 +    if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
   1.184 +        *fragmentStart = NULL;
   1.185 +        *fragmentContext = NULL;
   1.186 +        return E_FAIL;
   1.187 +    }
   1.188 +
   1.189 +    if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) {
   1.190 +        return E_FAIL;
   1.191 +    }
   1.192 +
   1.193 +    const void* data = fStream->getMemoryBase();
   1.194 +    if (NULL != data) {
   1.195 +        *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
   1.196 +        *fragmentContext = NULL;
   1.197 +
   1.198 +    } else {
   1.199 +        //May be called from multiple threads.
   1.200 +        SkAutoMutexAcquire ama(fStreamMutex);
   1.201 +
   1.202 +        *fragmentStart = NULL;
   1.203 +        *fragmentContext = NULL;
   1.204 +
   1.205 +        if (!fStream->rewind()) {
   1.206 +            return E_FAIL;
   1.207 +        }
   1.208 +        if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
   1.209 +            return E_FAIL;
   1.210 +        }
   1.211 +        SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
   1.212 +        if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
   1.213 +            return E_FAIL;
   1.214 +        }
   1.215 +
   1.216 +        *fragmentStart = streamData.get();
   1.217 +        *fragmentContext = streamData.detach();
   1.218 +    }
   1.219 +    return S_OK;
   1.220 +}
   1.221 +
   1.222 +void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
   1.223 +    sk_free(fragmentContext);
   1.224 +}
   1.225 +
   1.226 +HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
   1.227 +    *fileSize = fStream->getLength();
   1.228 +    return S_OK;
   1.229 +}
   1.230 +
   1.231 +HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
   1.232 +    // The concept of last write time does not apply to this loader.
   1.233 +    *lastWriteTime = 0;
   1.234 +    return E_NOTIMPL;
   1.235 +}

mercurial