tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxDWriteCommon.cpp (4738B)


      1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "gfxDWriteCommon.h"
      7 
      8 #include <unordered_map>
      9 
     10 #include "mozilla/StaticMutex.h"
     11 #include "mozilla/gfx/Logging.h"
     12 
     13 class gfxDWriteFontFileStream;
     14 
     15 using namespace mozilla;
     16 
     17 static StaticMutex sFontFileStreamsMutex MOZ_UNANNOTATED;
     18 static uint64_t sNextFontFileKey = 0;
     19 MOZ_RUNINIT static std::unordered_map<uint64_t, gfxDWriteFontFileStream*>
     20    sFontFileStreams;
     21 
     22 IDWriteFontFileLoader* gfxDWriteFontFileLoader::mInstance = nullptr;
     23 
     24 IFACEMETHODIMP_(ULONG) gfxDWriteFontFileStream::Release() {
     25  MOZ_ASSERT(0 != mRefCnt, "dup release");
     26  uint32_t count = --mRefCnt;
     27  if (count == 0) {
     28    // Avoid locking unless necessary. Verify the refcount hasn't changed
     29    // while locked. Delete within the scope of the lock when zero.
     30    StaticMutexAutoLock lock(sFontFileStreamsMutex);
     31    if (0 != mRefCnt) {
     32      return mRefCnt;
     33    }
     34    delete this;
     35  }
     36  return count;
     37 }
     38 
     39 gfxDWriteFontFileStream::gfxDWriteFontFileStream(const uint8_t* aData,
     40                                                 uint32_t aLength,
     41                                                 uint64_t aFontFileKey)
     42    : mFontFileKey(aFontFileKey) {
     43  // If this fails, mData will remain empty. That's OK: GetFileSize()
     44  // will then return 0, etc., and the font just won't load.
     45  if (!mData.AppendElements(aData, aLength, fallible_t())) {
     46    NS_WARNING("Failed to store data in gfxDWriteFontFileStream");
     47  }
     48 }
     49 
     50 gfxDWriteFontFileStream::~gfxDWriteFontFileStream() {
     51  sFontFileStreams.erase(mFontFileKey);
     52 }
     53 
     54 HRESULT STDMETHODCALLTYPE
     55 gfxDWriteFontFileStream::GetFileSize(UINT64* fileSize) {
     56  *fileSize = mData.Length();
     57  return S_OK;
     58 }
     59 
     60 HRESULT STDMETHODCALLTYPE
     61 gfxDWriteFontFileStream::GetLastWriteTime(UINT64* lastWriteTime) {
     62  return E_NOTIMPL;
     63 }
     64 
     65 HRESULT STDMETHODCALLTYPE gfxDWriteFontFileStream::ReadFileFragment(
     66    const void** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize,
     67    void** fragmentContext) {
     68  // We are required to do bounds checking.
     69  if (fileOffset + fragmentSize > (UINT64)mData.Length()) {
     70    return E_FAIL;
     71  }
     72  // We should be alive for the duration of this.
     73  *fragmentStart = &mData[fileOffset];
     74  *fragmentContext = nullptr;
     75  return S_OK;
     76 }
     77 
     78 void STDMETHODCALLTYPE
     79 gfxDWriteFontFileStream::ReleaseFileFragment(void* fragmentContext) {}
     80 
     81 HRESULT STDMETHODCALLTYPE gfxDWriteFontFileLoader::CreateStreamFromKey(
     82    const void* fontFileReferenceKey, UINT32 fontFileReferenceKeySize,
     83    IDWriteFontFileStream** fontFileStream) {
     84  if (!fontFileReferenceKey || !fontFileStream) {
     85    return E_POINTER;
     86  }
     87 
     88  StaticMutexAutoLock lock(sFontFileStreamsMutex);
     89  uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey);
     90  auto found = sFontFileStreams.find(fontFileKey);
     91  if (found == sFontFileStreams.end()) {
     92    *fontFileStream = nullptr;
     93    return E_FAIL;
     94  }
     95 
     96  found->second->AddRef();
     97  *fontFileStream = found->second;
     98  return S_OK;
     99 }
    100 
    101 /* static */
    102 HRESULT
    103 gfxDWriteFontFileLoader::CreateCustomFontFile(
    104    const uint8_t* aFontData, uint32_t aLength, IDWriteFontFile** aFontFile,
    105    gfxDWriteFontFileStream** aFontFileStream) {
    106  MOZ_ASSERT(aFontFile);
    107  MOZ_ASSERT(aFontFileStream);
    108 
    109  RefPtr<IDWriteFactory> factory = gfx::Factory::GetDWriteFactory();
    110  if (!factory) {
    111    gfxCriticalError()
    112        << "Failed to get DWrite Factory in CreateCustomFontFile.";
    113    return E_FAIL;
    114  }
    115 
    116  sFontFileStreamsMutex.Lock();
    117  uint64_t fontFileKey = sNextFontFileKey++;
    118  RefPtr<gfxDWriteFontFileStream> ffsRef =
    119      new gfxDWriteFontFileStream(aFontData, aLength, fontFileKey);
    120  sFontFileStreams[fontFileKey] = ffsRef;
    121  sFontFileStreamsMutex.Unlock();
    122 
    123  RefPtr<IDWriteFontFile> fontFile;
    124  HRESULT hr = factory->CreateCustomFontFileReference(
    125      &fontFileKey, sizeof(fontFileKey), Instance(), getter_AddRefs(fontFile));
    126  if (FAILED(hr)) {
    127    NS_WARNING("Failed to load font file from data!");
    128    return hr;
    129  }
    130 
    131  fontFile.forget(aFontFile);
    132  ffsRef.forget(aFontFileStream);
    133 
    134  return S_OK;
    135 }
    136 
    137 size_t gfxDWriteFontFileLoader::SizeOfIncludingThis(
    138    MallocSizeOf mallocSizeOf) const {
    139  // We are a singleton type that is effective owner of sFontFileStreams.
    140  MOZ_ASSERT(this == mInstance);
    141 
    142  size_t sizes = mallocSizeOf(this);
    143 
    144  // We don't have memory-reporting methods for a std::unordered_map, so just
    145  // take the size of the actual elements stored for now.
    146  sizes += sFontFileStreams.size() *
    147           (sizeof(uint64_t) + sizeof(gfxDWriteFontFileStream*));
    148 
    149  return sizes;
    150 }