tor-browser

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

FontFace.cpp (9507B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/FontFace.h"
      8 
      9 #include <algorithm>
     10 
     11 #include "gfxFontUtils.h"
     12 #include "mozilla/CycleCollectedJSContext.h"
     13 #include "mozilla/ServoBindings.h"
     14 #include "mozilla/ServoCSSParser.h"
     15 #include "mozilla/ServoStyleSet.h"
     16 #include "mozilla/ServoUtils.h"
     17 #include "mozilla/StaticPrefs_layout.h"
     18 #include "mozilla/dom/CSSFontFaceRule.h"
     19 #include "mozilla/dom/FontFaceBinding.h"
     20 #include "mozilla/dom/FontFaceImpl.h"
     21 #include "mozilla/dom/FontFaceSet.h"
     22 #include "mozilla/dom/Promise.h"
     23 #include "mozilla/dom/TypedArray.h"
     24 #include "mozilla/dom/UnionTypes.h"
     25 #include "nsStyleUtil.h"
     26 
     27 namespace mozilla::dom {
     28 
     29 // -- Utility functions ------------------------------------------------------
     30 
     31 template <typename T>
     32 static void GetDataFrom(const T& aObject, uint8_t*& aBuffer,
     33                        uint32_t& aLength) {
     34  MOZ_ASSERT(!aBuffer);
     35  // We need to use malloc here because the gfxUserFontEntry will be calling
     36  // free on it, so the Vector's default AllocPolicy (MallocAllocPolicy) is
     37  // fine.
     38  Maybe<Vector<uint8_t>> buffer =
     39      aObject.template CreateFromData<Vector<uint8_t>>();
     40  if (buffer.isNothing()) {
     41    return;
     42  }
     43  aLength = buffer->length();
     44  aBuffer = buffer->extractOrCopyRawBuffer();
     45 }
     46 
     47 // -- FontFace ---------------------------------------------------------------
     48 
     49 NS_IMPL_CYCLE_COLLECTION_CLASS(FontFace)
     50 
     51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FontFace)
     52  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoaded)
     53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     54 
     55 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FontFace)
     56  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoaded)
     57  tmp->Destroy();
     58  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     59 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     60 
     61 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(FontFace)
     62  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     63 NS_IMPL_CYCLE_COLLECTION_TRACE_END
     64 
     65 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FontFace)
     66  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     67  NS_INTERFACE_MAP_ENTRY(nsISupports)
     68 NS_INTERFACE_MAP_END
     69 
     70 NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace)
     71 NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace)
     72 
     73 FontFace::FontFace(nsIGlobalObject* aParent) { BindToOwner(aParent); }
     74 
     75 FontFace::~FontFace() {
     76  // Assert that we don't drop any FontFace objects during a Servo traversal,
     77  // since PostTraversalTask objects can hold raw pointers to FontFaces.
     78  MOZ_ASSERT(!gfxFontUtils::IsInServoTraversal());
     79  Destroy();
     80 }
     81 
     82 void FontFace::Destroy() { mImpl->Destroy(); }
     83 
     84 void FontFace::DisconnectFromOwner() {
     85  GlobalTeardownObserver::DisconnectFromOwner();
     86  if (mImpl) {
     87    mImpl->StopKeepingOwnerAlive();
     88  }
     89 }
     90 
     91 JSObject* FontFace::WrapObject(JSContext* aCx,
     92                               JS::Handle<JSObject*> aGivenProto) {
     93  return FontFace_Binding::Wrap(aCx, this, aGivenProto);
     94 }
     95 
     96 already_AddRefed<FontFace> FontFace::CreateForRule(
     97    nsIGlobalObject* aGlobal, FontFaceSet* aFontFaceSet,
     98    StyleLockedFontFaceRule* aRule) {
     99  FontFaceSetImpl* setImpl = aFontFaceSet->GetImpl();
    100  MOZ_ASSERT(setImpl);
    101 
    102  RefPtr<FontFace> obj = new FontFace(aGlobal);
    103  obj->mImpl = FontFaceImpl::CreateForRule(obj, setImpl, aRule);
    104  return obj.forget();
    105 }
    106 
    107 already_AddRefed<FontFace> FontFace::Constructor(
    108    const GlobalObject& aGlobal, const nsACString& aFamily,
    109    const UTF8StringOrArrayBufferOrArrayBufferView& aSource,
    110    const FontFaceDescriptors& aDescriptors, ErrorResult& aRv) {
    111  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
    112 
    113  FontFaceSet* set = global->GetFonts();
    114  if (NS_WARN_IF(!set)) {
    115    aRv.Throw(NS_ERROR_FAILURE);
    116    return nullptr;
    117  }
    118 
    119  FontFaceSetImpl* setImpl = set->GetImpl();
    120  if (NS_WARN_IF(!setImpl)) {
    121    aRv.Throw(NS_ERROR_FAILURE);
    122    return nullptr;
    123  }
    124 
    125  RefPtr<FontFace> obj = new FontFace(global);
    126  obj->mImpl = new FontFaceImpl(obj, setImpl);
    127  if (!obj->mImpl->SetDescriptors(aFamily, aDescriptors)) {
    128    return obj.forget();
    129  }
    130 
    131  if (aSource.IsUTF8String()) {
    132    obj->mImpl->InitializeSourceURL(aSource.GetAsUTF8String());
    133  } else {
    134    uint8_t* buffer = nullptr;
    135    uint32_t length = 0;
    136    if (aSource.IsArrayBuffer()) {
    137      GetDataFrom(aSource.GetAsArrayBuffer(), buffer, length);
    138    } else if (aSource.IsArrayBufferView()) {
    139      GetDataFrom(aSource.GetAsArrayBufferView(), buffer, length);
    140    } else {
    141      MOZ_ASSERT_UNREACHABLE("Unhandled source type!");
    142      return nullptr;
    143    }
    144 
    145    obj->mImpl->InitializeSourceBuffer(buffer, length);
    146  }
    147 
    148  return obj.forget();
    149 }
    150 
    151 void FontFace::GetFamily(nsACString& aResult) { mImpl->GetFamily(aResult); }
    152 
    153 void FontFace::SetFamily(const nsACString& aValue, ErrorResult& aRv) {
    154  mImpl->SetFamily(aValue, aRv);
    155 }
    156 
    157 void FontFace::GetStyle(nsACString& aResult) { mImpl->GetStyle(aResult); }
    158 
    159 void FontFace::SetStyle(const nsACString& aValue, ErrorResult& aRv) {
    160  mImpl->SetStyle(aValue, aRv);
    161 }
    162 
    163 void FontFace::GetWeight(nsACString& aResult) { mImpl->GetWeight(aResult); }
    164 
    165 void FontFace::SetWeight(const nsACString& aValue, ErrorResult& aRv) {
    166  mImpl->SetWeight(aValue, aRv);
    167 }
    168 
    169 void FontFace::GetStretch(nsACString& aResult) { mImpl->GetStretch(aResult); }
    170 
    171 void FontFace::SetStretch(const nsACString& aValue, ErrorResult& aRv) {
    172  mImpl->SetStretch(aValue, aRv);
    173 }
    174 
    175 void FontFace::GetUnicodeRange(nsACString& aResult) {
    176  mImpl->GetUnicodeRange(aResult);
    177 }
    178 
    179 void FontFace::SetUnicodeRange(const nsACString& aValue, ErrorResult& aRv) {
    180  mImpl->SetUnicodeRange(aValue, aRv);
    181 }
    182 
    183 void FontFace::GetVariant(nsACString& aResult) { mImpl->GetVariant(aResult); }
    184 
    185 void FontFace::SetVariant(const nsACString& aValue, ErrorResult& aRv) {
    186  mImpl->SetVariant(aValue, aRv);
    187 }
    188 
    189 void FontFace::GetFeatureSettings(nsACString& aResult) {
    190  mImpl->GetFeatureSettings(aResult);
    191 }
    192 
    193 void FontFace::SetFeatureSettings(const nsACString& aValue, ErrorResult& aRv) {
    194  mImpl->SetFeatureSettings(aValue, aRv);
    195 }
    196 
    197 void FontFace::GetVariationSettings(nsACString& aResult) {
    198  mImpl->GetVariationSettings(aResult);
    199 }
    200 
    201 void FontFace::SetVariationSettings(const nsACString& aValue,
    202                                    ErrorResult& aRv) {
    203  mImpl->SetVariationSettings(aValue, aRv);
    204 }
    205 
    206 void FontFace::GetDisplay(nsACString& aResult) { mImpl->GetDisplay(aResult); }
    207 
    208 void FontFace::SetDisplay(const nsACString& aValue, ErrorResult& aRv) {
    209  mImpl->SetDisplay(aValue, aRv);
    210 }
    211 
    212 void FontFace::GetAscentOverride(nsACString& aResult) {
    213  mImpl->GetAscentOverride(aResult);
    214 }
    215 
    216 void FontFace::SetAscentOverride(const nsACString& aValue, ErrorResult& aRv) {
    217  mImpl->SetAscentOverride(aValue, aRv);
    218 }
    219 
    220 void FontFace::GetDescentOverride(nsACString& aResult) {
    221  mImpl->GetDescentOverride(aResult);
    222 }
    223 
    224 void FontFace::SetDescentOverride(const nsACString& aValue, ErrorResult& aRv) {
    225  mImpl->SetDescentOverride(aValue, aRv);
    226 }
    227 
    228 void FontFace::GetLineGapOverride(nsACString& aResult) {
    229  mImpl->GetLineGapOverride(aResult);
    230 }
    231 
    232 void FontFace::SetLineGapOverride(const nsACString& aValue, ErrorResult& aRv) {
    233  mImpl->SetLineGapOverride(aValue, aRv);
    234 }
    235 
    236 void FontFace::GetSizeAdjust(nsACString& aResult) {
    237  mImpl->GetSizeAdjust(aResult);
    238 }
    239 
    240 void FontFace::SetSizeAdjust(const nsACString& aValue, ErrorResult& aRv) {
    241  mImpl->SetSizeAdjust(aValue, aRv);
    242 }
    243 
    244 FontFaceLoadStatus FontFace::Status() { return mImpl->Status(); }
    245 
    246 Promise* FontFace::Load(ErrorResult& aRv) {
    247  EnsurePromise();
    248 
    249  if (!mLoaded) {
    250    aRv.Throw(NS_ERROR_FAILURE);
    251    return nullptr;
    252  }
    253 
    254  mImpl->Load(aRv);
    255  return mLoaded;
    256 }
    257 
    258 Promise* FontFace::GetLoaded(ErrorResult& aRv) {
    259  EnsurePromise();
    260 
    261  if (!mLoaded) {
    262    aRv.Throw(NS_ERROR_FAILURE);
    263    return nullptr;
    264  }
    265 
    266  return mLoaded;
    267 }
    268 
    269 void FontFace::MaybeResolve() {
    270  gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
    271 
    272  if (!mLoaded) {
    273    return;
    274  }
    275 
    276  if (ServoStyleSet* ss = gfxFontUtils::CurrentServoStyleSet()) {
    277    // See comments in Gecko_GetFontMetrics.
    278    ss->AppendTask(PostTraversalTask::ResolveFontFaceLoadedPromise(this));
    279    return;
    280  }
    281 
    282  mLoaded->MaybeResolve(this);
    283 }
    284 
    285 void FontFace::MaybeReject(FontFaceLoadedRejectReason aReason,
    286                           nsCString&& aMessage) {
    287  gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
    288 
    289  if (ServoStyleSet* ss = gfxFontUtils::CurrentServoStyleSet()) {
    290    // See comments in Gecko_GetFontMetrics.
    291    ss->AppendTask(PostTraversalTask::RejectFontFaceLoadedPromise(
    292        this, aReason, std::move(aMessage)));
    293    return;
    294  }
    295 
    296  if (mLoaded) {
    297    switch (aReason) {
    298      case FontFaceLoadedRejectReason::Network:
    299        mLoaded->MaybeRejectWithNetworkError(aMessage);
    300        break;
    301      case FontFaceLoadedRejectReason::Syntax:
    302        mLoaded->MaybeRejectWithSyntaxError(aMessage);
    303        break;
    304    }
    305  } else if (!mLoadedRejection) {
    306    mLoadedRejection = MakeUnique<FontFaceLoadedRejection>(
    307        FontFaceLoadedRejection{aReason, std::move(aMessage)});
    308  }
    309 }
    310 
    311 void FontFace::EnsurePromise() {
    312  if (mLoaded || !mImpl || !GetOwnerGlobal()) {
    313    return;
    314  }
    315 
    316  mLoaded = Promise::CreateInfallible(GetOwnerGlobal());
    317 
    318  if (mImpl->Status() == FontFaceLoadStatus::Loaded) {
    319    mLoaded->MaybeResolve(this);
    320  } else if (mLoadedRejection) {
    321    auto rejection = std::move(mLoadedRejection);
    322    MaybeReject(rejection->mReason, std::move(rejection->mMessage));
    323  }
    324 }
    325 
    326 }  // namespace mozilla::dom