LCOV - code coverage report
Current view: top level - layout/style - FontFace.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 405 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; 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 "mozilla/dom/FontFace.h"
       7             : 
       8             : #include <algorithm>
       9             : #include "mozilla/dom/FontFaceBinding.h"
      10             : #include "mozilla/dom/FontFaceSet.h"
      11             : #include "mozilla/dom/Promise.h"
      12             : #include "mozilla/dom/TypedArray.h"
      13             : #include "mozilla/dom/UnionTypes.h"
      14             : #include "mozilla/CycleCollectedJSContext.h"
      15             : #include "mozilla/ServoStyleSet.h"
      16             : #include "mozilla/ServoUtils.h"
      17             : #include "nsCSSFontFaceRule.h"
      18             : #include "nsCSSParser.h"
      19             : #include "nsIDocument.h"
      20             : #include "nsStyleUtil.h"
      21             : 
      22             : namespace mozilla {
      23             : namespace dom {
      24             : 
      25             : // -- FontFaceBufferSource ---------------------------------------------------
      26             : 
      27             : /**
      28             :  * An object that wraps a FontFace object and exposes its ArrayBuffer
      29             :  * or ArrayBufferView data in a form the user font set can consume.
      30             :  */
      31           0 : class FontFaceBufferSource : public gfxFontFaceBufferSource
      32             : {
      33             : public:
      34           0 :   explicit FontFaceBufferSource(FontFace* aFontFace)
      35           0 :     : mFontFace(aFontFace) {}
      36             :   virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength);
      37             : 
      38             : private:
      39             :   RefPtr<FontFace> mFontFace;
      40             : };
      41             : 
      42             : void
      43           0 : FontFaceBufferSource::TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength)
      44             : {
      45           0 :   MOZ_ASSERT(mFontFace, "only call TakeBuffer once on a given "
      46             :                         "FontFaceBufferSource object");
      47           0 :   mFontFace->TakeBuffer(aBuffer, aLength);
      48           0 :   mFontFace = nullptr;
      49           0 : }
      50             : 
      51             : // -- Utility functions ------------------------------------------------------
      52             : 
      53             : template<typename T>
      54             : static void
      55           0 : GetDataFrom(const T& aObject, uint8_t*& aBuffer, uint32_t& aLength)
      56             : {
      57           0 :   MOZ_ASSERT(!aBuffer);
      58           0 :   aObject.ComputeLengthAndData();
      59             :   // We use malloc here rather than a FallibleTArray or fallible
      60             :   // operator new[] since the gfxUserFontEntry will be calling free
      61             :   // on it.
      62           0 :   aBuffer = (uint8_t*) malloc(aObject.Length());
      63           0 :   if (!aBuffer) {
      64           0 :     return;
      65             :   }
      66           0 :   memcpy((void*) aBuffer, aObject.Data(), aObject.Length());
      67           0 :   aLength = aObject.Length();
      68             : }
      69             : 
      70             : // -- FontFace ---------------------------------------------------------------
      71             : 
      72             : NS_IMPL_CYCLE_COLLECTION_CLASS(FontFace)
      73             : 
      74           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FontFace)
      75           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
      76           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoaded)
      77           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRule)
      78           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet)
      79           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOtherFontFaceSets)
      80           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      81             : 
      82           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FontFace)
      83           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
      84           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoaded)
      85           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRule)
      86           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
      87           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOtherFontFaceSets)
      88           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      89           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      90             : 
      91           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(FontFace)
      92           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
      93           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      94             : 
      95           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FontFace)
      96           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      97           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      98           0 : NS_INTERFACE_MAP_END
      99             : 
     100           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace)
     101           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace)
     102             : 
     103           0 : FontFace::FontFace(nsISupports* aParent, FontFaceSet* aFontFaceSet)
     104             :   : mParent(aParent)
     105             :   , mLoadedRejection(NS_OK)
     106             :   , mStatus(FontFaceLoadStatus::Unloaded)
     107             :   , mSourceType(SourceType(0))
     108             :   , mSourceBuffer(nullptr)
     109             :   , mSourceBufferLength(0)
     110             :   , mFontFaceSet(aFontFaceSet)
     111             :   , mUnicodeRangeDirty(true)
     112           0 :   , mInFontFaceSet(false)
     113             : {
     114           0 : }
     115             : 
     116           0 : FontFace::~FontFace()
     117             : {
     118             :   // Assert that we don't drop any FontFace objects during a Servo traversal,
     119             :   // since PostTraversalTask objects can hold raw pointers to FontFaces.
     120           0 :   MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
     121             : 
     122           0 :   SetUserFontEntry(nullptr);
     123             : 
     124           0 :   if (mSourceBuffer) {
     125           0 :     free(mSourceBuffer);
     126             :   }
     127           0 : }
     128             : 
     129             : JSObject*
     130           0 : FontFace::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     131             : {
     132           0 :   return FontFaceBinding::Wrap(aCx, this, aGivenProto);
     133             : }
     134             : 
     135             : static FontFaceLoadStatus
     136           0 : LoadStateToStatus(gfxUserFontEntry::UserFontLoadState aLoadState)
     137             : {
     138           0 :   switch (aLoadState) {
     139             :     case gfxUserFontEntry::UserFontLoadState::STATUS_NOT_LOADED:
     140           0 :       return FontFaceLoadStatus::Unloaded;
     141             :     case gfxUserFontEntry::UserFontLoadState::STATUS_LOAD_PENDING:
     142             :     case gfxUserFontEntry::UserFontLoadState::STATUS_LOADING:
     143           0 :       return FontFaceLoadStatus::Loading;
     144             :     case gfxUserFontEntry::UserFontLoadState::STATUS_LOADED:
     145           0 :       return FontFaceLoadStatus::Loaded;
     146             :     case gfxUserFontEntry::UserFontLoadState::STATUS_FAILED:
     147           0 :       return FontFaceLoadStatus::Error;
     148             :   }
     149           0 :   NS_NOTREACHED("invalid aLoadState value");
     150           0 :   return FontFaceLoadStatus::Error;
     151             : }
     152             : 
     153             : already_AddRefed<FontFace>
     154           0 : FontFace::CreateForRule(nsISupports* aGlobal,
     155             :                         FontFaceSet* aFontFaceSet,
     156             :                         nsCSSFontFaceRule* aRule)
     157             : {
     158           0 :   RefPtr<FontFace> obj = new FontFace(aGlobal, aFontFaceSet);
     159           0 :   obj->mRule = aRule;
     160           0 :   obj->mSourceType = eSourceType_FontFaceRule;
     161           0 :   obj->mInFontFaceSet = true;
     162           0 :   return obj.forget();
     163             : }
     164             : 
     165             : already_AddRefed<FontFace>
     166           0 : FontFace::Constructor(const GlobalObject& aGlobal,
     167             :                       const nsAString& aFamily,
     168             :                       const StringOrArrayBufferOrArrayBufferView& aSource,
     169             :                       const FontFaceDescriptors& aDescriptors,
     170             :                       ErrorResult& aRv)
     171             : {
     172           0 :   nsISupports* global = aGlobal.GetAsSupports();
     173           0 :   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
     174           0 :   nsIDocument* doc = window->GetDoc();
     175           0 :   if (!doc) {
     176           0 :     aRv.Throw(NS_ERROR_FAILURE);
     177           0 :     return nullptr;
     178             :   }
     179             : 
     180           0 :   RefPtr<FontFace> obj = new FontFace(global, doc->Fonts());
     181           0 :   if (!obj->SetDescriptors(aFamily, aDescriptors)) {
     182           0 :     return obj.forget();
     183             :   }
     184             : 
     185           0 :   obj->InitializeSource(aSource);
     186           0 :   return obj.forget();
     187             : }
     188             : 
     189             : void
     190           0 : FontFace::InitializeSource(const StringOrArrayBufferOrArrayBufferView& aSource)
     191             : {
     192           0 :   if (aSource.IsString()) {
     193           0 :     if (!ParseDescriptor(eCSSFontDesc_Src,
     194             :                          aSource.GetAsString(),
     195           0 :                          mDescriptors->mSrc)) {
     196           0 :       Reject(NS_ERROR_DOM_SYNTAX_ERR);
     197             : 
     198           0 :       SetStatus(FontFaceLoadStatus::Error);
     199           0 :       return;
     200             :     }
     201             : 
     202           0 :     mSourceType = eSourceType_URLs;
     203           0 :     return;
     204             :   }
     205             : 
     206           0 :   mSourceType = FontFace::eSourceType_Buffer;
     207             : 
     208           0 :   if (aSource.IsArrayBuffer()) {
     209           0 :     GetDataFrom(aSource.GetAsArrayBuffer(),
     210           0 :                 mSourceBuffer, mSourceBufferLength);
     211             :   } else {
     212           0 :     MOZ_ASSERT(aSource.IsArrayBufferView());
     213           0 :     GetDataFrom(aSource.GetAsArrayBufferView(),
     214           0 :                 mSourceBuffer, mSourceBufferLength);
     215             :   }
     216             : 
     217           0 :   SetStatus(FontFaceLoadStatus::Loading);
     218           0 :   DoLoad();
     219             : }
     220             : 
     221             : void
     222           0 : FontFace::GetFamily(nsString& aResult)
     223             : {
     224           0 :   mFontFaceSet->FlushUserFontSet();
     225             : 
     226             :   // Serialize the same way as in nsCSSFontFaceStyleDecl::GetPropertyValue.
     227           0 :   nsCSSValue value;
     228           0 :   GetDesc(eCSSFontDesc_Family, value);
     229             : 
     230           0 :   aResult.Truncate();
     231             : 
     232           0 :   if (value.GetUnit() == eCSSUnit_Null) {
     233           0 :     return;
     234             :   }
     235             : 
     236           0 :   nsDependentString family(value.GetStringBufferValue());
     237           0 :   if (!family.IsEmpty()) {
     238             :     // The string length can be zero when the author passed an invalid
     239             :     // family name or an invalid descriptor to the JS FontFace constructor.
     240           0 :     nsStyleUtil::AppendEscapedCSSString(family, aResult);
     241             :   }
     242             : }
     243             : 
     244             : void
     245           0 : FontFace::SetFamily(const nsAString& aValue, ErrorResult& aRv)
     246             : {
     247           0 :   mFontFaceSet->FlushUserFontSet();
     248           0 :   SetDescriptor(eCSSFontDesc_Family, aValue, aRv);
     249           0 : }
     250             : 
     251             : void
     252           0 : FontFace::GetStyle(nsString& aResult)
     253             : {
     254           0 :   mFontFaceSet->FlushUserFontSet();
     255           0 :   GetDesc(eCSSFontDesc_Style, eCSSProperty_font_style, aResult);
     256           0 : }
     257             : 
     258             : void
     259           0 : FontFace::SetStyle(const nsAString& aValue, ErrorResult& aRv)
     260             : {
     261           0 :   mFontFaceSet->FlushUserFontSet();
     262           0 :   SetDescriptor(eCSSFontDesc_Style, aValue, aRv);
     263           0 : }
     264             : 
     265             : void
     266           0 : FontFace::GetWeight(nsString& aResult)
     267             : {
     268           0 :   mFontFaceSet->FlushUserFontSet();
     269           0 :   GetDesc(eCSSFontDesc_Weight, eCSSProperty_font_weight, aResult);
     270           0 : }
     271             : 
     272             : void
     273           0 : FontFace::SetWeight(const nsAString& aValue, ErrorResult& aRv)
     274             : {
     275           0 :   mFontFaceSet->FlushUserFontSet();
     276           0 :   SetDescriptor(eCSSFontDesc_Weight, aValue, aRv);
     277           0 : }
     278             : 
     279             : void
     280           0 : FontFace::GetStretch(nsString& aResult)
     281             : {
     282           0 :   mFontFaceSet->FlushUserFontSet();
     283           0 :   GetDesc(eCSSFontDesc_Stretch, eCSSProperty_font_stretch, aResult);
     284           0 : }
     285             : 
     286             : void
     287           0 : FontFace::SetStretch(const nsAString& aValue, ErrorResult& aRv)
     288             : {
     289           0 :   mFontFaceSet->FlushUserFontSet();
     290           0 :   SetDescriptor(eCSSFontDesc_Stretch, aValue, aRv);
     291           0 : }
     292             : 
     293             : void
     294           0 : FontFace::GetUnicodeRange(nsString& aResult)
     295             : {
     296           0 :   mFontFaceSet->FlushUserFontSet();
     297             : 
     298             :   // There is no eCSSProperty_unicode_range for us to pass in to GetDesc
     299             :   // to get a serialized (possibly defaulted) value, but that function
     300             :   // doesn't use the property ID for this descriptor anyway.
     301           0 :   GetDesc(eCSSFontDesc_UnicodeRange, eCSSProperty_UNKNOWN, aResult);
     302           0 : }
     303             : 
     304             : void
     305           0 : FontFace::SetUnicodeRange(const nsAString& aValue, ErrorResult& aRv)
     306             : {
     307           0 :   mFontFaceSet->FlushUserFontSet();
     308           0 :   SetDescriptor(eCSSFontDesc_UnicodeRange, aValue, aRv);
     309           0 : }
     310             : 
     311             : void
     312           0 : FontFace::GetVariant(nsString& aResult)
     313             : {
     314           0 :   mFontFaceSet->FlushUserFontSet();
     315             : 
     316             :   // XXX Just expose the font-variant descriptor as "normal" until we
     317             :   // support it properly (bug 1055385).
     318           0 :   aResult.AssignLiteral("normal");
     319           0 : }
     320             : 
     321             : void
     322           0 : FontFace::SetVariant(const nsAString& aValue, ErrorResult& aRv)
     323             : {
     324           0 :   mFontFaceSet->FlushUserFontSet();
     325             : 
     326             :   // XXX Ignore assignments to variant until we support font-variant
     327             :   // descriptors (bug 1055385).
     328           0 : }
     329             : 
     330             : void
     331           0 : FontFace::GetFeatureSettings(nsString& aResult)
     332             : {
     333           0 :   mFontFaceSet->FlushUserFontSet();
     334             :   GetDesc(eCSSFontDesc_FontFeatureSettings, eCSSProperty_font_feature_settings,
     335           0 :           aResult);
     336           0 : }
     337             : 
     338             : void
     339           0 : FontFace::SetFeatureSettings(const nsAString& aValue, ErrorResult& aRv)
     340             : {
     341           0 :   mFontFaceSet->FlushUserFontSet();
     342           0 :   SetDescriptor(eCSSFontDesc_FontFeatureSettings, aValue, aRv);
     343           0 : }
     344             : 
     345             : void
     346           0 : FontFace::GetDisplay(nsString& aResult)
     347             : {
     348           0 :   mFontFaceSet->FlushUserFontSet();
     349           0 :   GetDesc(eCSSFontDesc_Display, eCSSProperty_UNKNOWN, aResult);
     350           0 : }
     351             : 
     352             : void
     353           0 : FontFace::SetDisplay(const nsAString& aValue, ErrorResult& aRv)
     354             : {
     355           0 :   mFontFaceSet->FlushUserFontSet();
     356           0 :   SetDescriptor(eCSSFontDesc_Display, aValue, aRv);
     357           0 : }
     358             : 
     359             : FontFaceLoadStatus
     360           0 : FontFace::Status()
     361             : {
     362           0 :   return mStatus;
     363             : }
     364             : 
     365             : Promise*
     366           0 : FontFace::Load(ErrorResult& aRv)
     367             : {
     368           0 :   MOZ_ASSERT(NS_IsMainThread());
     369             : 
     370           0 :   mFontFaceSet->FlushUserFontSet();
     371             : 
     372           0 :   EnsurePromise();
     373             : 
     374           0 :   if (!mLoaded) {
     375           0 :     aRv.Throw(NS_ERROR_FAILURE);
     376           0 :     return nullptr;
     377             :   }
     378             : 
     379             :   // Calling Load on a FontFace constructed with an ArrayBuffer data source,
     380             :   // or on one that is already loading (or has finished loading), has no
     381             :   // effect.
     382           0 :   if (mSourceType == eSourceType_Buffer ||
     383           0 :       mStatus != FontFaceLoadStatus::Unloaded) {
     384           0 :     return mLoaded;
     385             :   }
     386             : 
     387             :   // Calling the user font entry's Load method will end up setting our
     388             :   // status to Loading, but the spec requires us to set it to Loading
     389             :   // here.
     390           0 :   SetStatus(FontFaceLoadStatus::Loading);
     391             : 
     392           0 :   DoLoad();
     393             : 
     394           0 :   return mLoaded;
     395             : }
     396             : 
     397             : gfxUserFontEntry*
     398           0 : FontFace::CreateUserFontEntry()
     399             : {
     400           0 :   if (!mUserFontEntry) {
     401           0 :     MOZ_ASSERT(!HasRule(),
     402             :                "Rule backed FontFace objects should already have a user font "
     403             :                "entry by the time Load() can be called on them");
     404             : 
     405             :     RefPtr<gfxUserFontEntry> newEntry =
     406           0 :       mFontFaceSet->FindOrCreateUserFontEntryFromFontFace(this);
     407           0 :     if (newEntry) {
     408           0 :       SetUserFontEntry(newEntry);
     409             :     }
     410             :   }
     411             : 
     412           0 :   return mUserFontEntry;
     413             : }
     414             : 
     415             : void
     416           0 : FontFace::DoLoad()
     417             : {
     418           0 :   if (!CreateUserFontEntry()) {
     419           0 :     return;
     420             :   }
     421           0 :   mUserFontEntry->Load();
     422             : }
     423             : 
     424             : Promise*
     425           0 : FontFace::GetLoaded(ErrorResult& aRv)
     426             : {
     427           0 :   MOZ_ASSERT(NS_IsMainThread());
     428             : 
     429           0 :   mFontFaceSet->FlushUserFontSet();
     430             : 
     431           0 :   EnsurePromise();
     432             : 
     433           0 :   if (!mLoaded) {
     434           0 :     aRv.Throw(NS_ERROR_FAILURE);
     435           0 :     return nullptr;
     436             :   }
     437             : 
     438           0 :   return mLoaded;
     439             : }
     440             : 
     441             : void
     442           0 : FontFace::SetStatus(FontFaceLoadStatus aStatus)
     443             : {
     444           0 :   AssertIsMainThreadOrServoFontMetricsLocked();
     445             : 
     446           0 :   if (mStatus == aStatus) {
     447           0 :     return;
     448             :   }
     449             : 
     450           0 :   if (aStatus < mStatus) {
     451             :     // We're being asked to go backwards in status!  Normally, this shouldn't
     452             :     // happen.  But it can if the FontFace had a user font entry that had
     453             :     // loaded, but then was given a new one by FontFaceSet::InsertRuleFontFace
     454             :     // if we used a local() rule.  For now, just ignore the request to
     455             :     // go backwards in status.
     456           0 :     return;
     457             :   }
     458             : 
     459           0 :   mStatus = aStatus;
     460             : 
     461           0 :   if (mInFontFaceSet) {
     462           0 :     mFontFaceSet->OnFontFaceStatusChanged(this);
     463             :   }
     464             : 
     465           0 :   for (FontFaceSet* otherSet : mOtherFontFaceSets) {
     466           0 :     otherSet->OnFontFaceStatusChanged(this);
     467             :   }
     468             : 
     469           0 :   if (mStatus == FontFaceLoadStatus::Loaded) {
     470           0 :     if (mLoaded) {
     471           0 :       DoResolve();
     472             :     }
     473           0 :   } else if (mStatus == FontFaceLoadStatus::Error) {
     474           0 :     if (mSourceType == eSourceType_Buffer) {
     475           0 :       Reject(NS_ERROR_DOM_SYNTAX_ERR);
     476             :     } else {
     477           0 :       Reject(NS_ERROR_DOM_NETWORK_ERR);
     478             :     }
     479             :   }
     480             : }
     481             : 
     482             : void
     483           0 : FontFace::DoResolve()
     484             : {
     485           0 :   AssertIsMainThreadOrServoFontMetricsLocked();
     486             : 
     487           0 :   if (ServoStyleSet* ss = ServoStyleSet::Current()) {
     488             :     // See comments in Gecko_GetFontMetrics.
     489           0 :     ss->AppendTask(PostTraversalTask::ResolveFontFaceLoadedPromise(this));
     490           0 :     return;
     491             :   }
     492             : 
     493           0 :   mLoaded->MaybeResolve(this);
     494             : }
     495             : 
     496             : void
     497           0 : FontFace::DoReject(nsresult aResult)
     498             : {
     499           0 :   AssertIsMainThreadOrServoFontMetricsLocked();
     500             : 
     501           0 :   if (ServoStyleSet* ss = ServoStyleSet::Current()) {
     502             :     // See comments in Gecko_GetFontMetrics.
     503           0 :     ss->AppendTask(PostTraversalTask::RejectFontFaceLoadedPromise(this, aResult));
     504           0 :     return;
     505             :   }
     506             : 
     507           0 :   mLoaded->MaybeReject(aResult);
     508             : }
     509             : 
     510             : bool
     511           0 : FontFace::ParseDescriptor(nsCSSFontDesc aDescID,
     512             :                           const nsAString& aString,
     513             :                           nsCSSValue& aResult)
     514             : {
     515           0 :   nsCSSParser parser;
     516             : 
     517           0 :   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
     518           0 :   nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
     519             : 
     520           0 :   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mParent);
     521           0 :   nsCOMPtr<nsIURI> docURI = window->GetDocumentURI();
     522           0 :   nsCOMPtr<nsIURI> base = window->GetDocBaseURI();
     523             : 
     524           0 :   if (!parser.ParseFontFaceDescriptor(aDescID, aString,
     525             :                                       docURI, // aSheetURL
     526             :                                       base,
     527             :                                       principal,
     528             :                                       aResult)) {
     529           0 :     aResult.Reset();
     530           0 :     return false;
     531             :   }
     532             : 
     533           0 :   return true;
     534             : }
     535             : 
     536             : void
     537           0 : FontFace::SetDescriptor(nsCSSFontDesc aFontDesc,
     538             :                         const nsAString& aValue,
     539             :                         ErrorResult& aRv)
     540             : {
     541           0 :   NS_ASSERTION(!HasRule(),
     542             :                "we don't handle rule backed FontFace objects yet");
     543           0 :   if (HasRule()) {
     544           0 :     return;
     545             :   }
     546             : 
     547           0 :   nsCSSValue parsedValue;
     548           0 :   if (!ParseDescriptor(aFontDesc, aValue, parsedValue)) {
     549           0 :     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     550           0 :     return;
     551             :   }
     552             : 
     553           0 :   mDescriptors->Get(aFontDesc) = parsedValue;
     554             : 
     555           0 :   if (aFontDesc == eCSSFontDesc_UnicodeRange) {
     556           0 :     mUnicodeRangeDirty = true;
     557             :   }
     558             : 
     559             :   // XXX Setting descriptors doesn't actually have any effect on FontFace
     560             :   // objects that have started loading or have already been loaded.
     561             : }
     562             : 
     563             : bool
     564           0 : FontFace::SetDescriptors(const nsAString& aFamily,
     565             :                          const FontFaceDescriptors& aDescriptors)
     566             : {
     567           0 :   MOZ_ASSERT(!HasRule());
     568           0 :   MOZ_ASSERT(!mDescriptors);
     569             : 
     570           0 :   mDescriptors = new CSSFontFaceDescriptors;
     571             : 
     572             :   // Parse all of the mDescriptors in aInitializer, which are the values
     573             :   // we got from the JS constructor.
     574           0 :   if (!ParseDescriptor(eCSSFontDesc_Family,
     575             :                        aFamily,
     576           0 :                        mDescriptors->mFamily) ||
     577           0 :       *mDescriptors->mFamily.GetStringBufferValue() == 0 ||
     578           0 :       !ParseDescriptor(eCSSFontDesc_Style,
     579             :                        aDescriptors.mStyle,
     580           0 :                        mDescriptors->mStyle) ||
     581           0 :       !ParseDescriptor(eCSSFontDesc_Weight,
     582             :                        aDescriptors.mWeight,
     583           0 :                        mDescriptors->mWeight) ||
     584           0 :       !ParseDescriptor(eCSSFontDesc_Stretch,
     585             :                        aDescriptors.mStretch,
     586           0 :                        mDescriptors->mStretch) ||
     587           0 :       !ParseDescriptor(eCSSFontDesc_UnicodeRange,
     588             :                        aDescriptors.mUnicodeRange,
     589           0 :                        mDescriptors->mUnicodeRange) ||
     590           0 :       !ParseDescriptor(eCSSFontDesc_FontFeatureSettings,
     591             :                        aDescriptors.mFeatureSettings,
     592           0 :                        mDescriptors->mFontFeatureSettings) ||
     593           0 :       !ParseDescriptor(eCSSFontDesc_Display,
     594             :                        aDescriptors.mDisplay,
     595           0 :                        mDescriptors->mDisplay)) {
     596             :     // XXX Handle font-variant once we support it (bug 1055385).
     597             : 
     598             :     // If any of the descriptors failed to parse, none of them should be set
     599             :     // on the FontFace.
     600           0 :     mDescriptors = new CSSFontFaceDescriptors;
     601             : 
     602           0 :     Reject(NS_ERROR_DOM_SYNTAX_ERR);
     603             : 
     604           0 :     SetStatus(FontFaceLoadStatus::Error);
     605           0 :     return false;
     606             :   }
     607             : 
     608           0 :   return true;
     609             : }
     610             : 
     611             : void
     612           0 : FontFace::GetDesc(nsCSSFontDesc aDescID, nsCSSValue& aResult) const
     613             : {
     614           0 :   if (HasRule()) {
     615           0 :     MOZ_ASSERT(mRule);
     616           0 :     MOZ_ASSERT(!mDescriptors);
     617           0 :     mRule->GetDesc(aDescID, aResult);
     618             :   } else {
     619           0 :     aResult = mDescriptors->Get(aDescID);
     620             :   }
     621           0 : }
     622             : 
     623             : void
     624           0 : FontFace::GetDesc(nsCSSFontDesc aDescID,
     625             :                   nsCSSPropertyID aPropID,
     626             :                   nsString& aResult) const
     627             : {
     628           0 :   MOZ_ASSERT(aDescID == eCSSFontDesc_UnicodeRange ||
     629             :              aDescID == eCSSFontDesc_Display ||
     630             :              aPropID != eCSSProperty_UNKNOWN,
     631             :              "only pass eCSSProperty_UNKNOWN for eCSSFontDesc_UnicodeRange");
     632             : 
     633           0 :   nsCSSValue value;
     634           0 :   GetDesc(aDescID, value);
     635             : 
     636           0 :   aResult.Truncate();
     637             : 
     638             :   // Fill in a default value for missing descriptors.
     639           0 :   if (value.GetUnit() == eCSSUnit_Null) {
     640           0 :     if (aDescID == eCSSFontDesc_UnicodeRange) {
     641           0 :       aResult.AssignLiteral("U+0-10FFFF");
     642           0 :     } else if (aDescID == eCSSFontDesc_Display) {
     643           0 :       aResult.AssignLiteral("auto");
     644           0 :     } else if (aDescID != eCSSFontDesc_Family &&
     645             :                aDescID != eCSSFontDesc_Src) {
     646           0 :       aResult.AssignLiteral("normal");
     647             :     }
     648           0 :     return;
     649             :   }
     650             : 
     651           0 :   if (aDescID == eCSSFontDesc_UnicodeRange) {
     652             :     // Since there's no unicode-range property, we can't use
     653             :     // nsCSSValue::AppendToString to serialize this descriptor.
     654           0 :     nsStyleUtil::AppendUnicodeRange(value, aResult);
     655           0 :   } else if (aDescID == eCSSFontDesc_Display) {
     656           0 :     AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(value.GetIntValue(),
     657           0 :                                                   nsCSSProps::kFontDisplayKTable),
     658           0 :                        aResult);
     659             :   } else {
     660           0 :     value.AppendToString(aPropID, aResult, nsCSSValue::eNormalized);
     661             :   }
     662             : }
     663             : 
     664             : void
     665           0 : FontFace::SetUserFontEntry(gfxUserFontEntry* aEntry)
     666             : {
     667           0 :   if (mUserFontEntry) {
     668           0 :     mUserFontEntry->mFontFaces.RemoveElement(this);
     669             :   }
     670             : 
     671           0 :   mUserFontEntry = static_cast<Entry*>(aEntry);
     672           0 :   if (mUserFontEntry) {
     673           0 :     mUserFontEntry->mFontFaces.AppendElement(this);
     674             : 
     675             :     // Our newly assigned user font entry might be in the process of or
     676             :     // finished loading, so set our status accordingly.  But only do so
     677             :     // if we're not going "backwards" in status, which could otherwise
     678             :     // happen in this case:
     679             :     //
     680             :     //   new FontFace("ABC", "url(x)").load();
     681             :     //
     682             :     // where the SetUserFontEntry call (from the after-initialization
     683             :     // DoLoad call) comes after the author's call to load(), which set mStatus
     684             :     // to Loading.
     685             :     FontFaceLoadStatus newStatus =
     686           0 :       LoadStateToStatus(mUserFontEntry->LoadState());
     687           0 :     if (newStatus > mStatus) {
     688           0 :       SetStatus(newStatus);
     689             :     }
     690             :   }
     691           0 : }
     692             : 
     693             : bool
     694           0 : FontFace::GetFamilyName(nsString& aResult)
     695             : {
     696           0 :   nsCSSValue value;
     697           0 :   GetDesc(eCSSFontDesc_Family, value);
     698             : 
     699           0 :   if (value.GetUnit() == eCSSUnit_String) {
     700           0 :     nsString familyname;
     701           0 :     value.GetStringValue(familyname);
     702           0 :     aResult.Append(familyname);
     703             :   }
     704             : 
     705           0 :   return !aResult.IsEmpty();
     706             : }
     707             : 
     708             : void
     709           0 : FontFace::DisconnectFromRule()
     710             : {
     711           0 :   MOZ_ASSERT(HasRule());
     712             : 
     713             :   // Make a copy of the descriptors.
     714           0 :   mDescriptors = new CSSFontFaceDescriptors;
     715           0 :   mRule->GetDescriptors(*mDescriptors);
     716           0 :   mRule = nullptr;
     717           0 :   mInFontFaceSet = false;
     718           0 : }
     719             : 
     720             : bool
     721           0 : FontFace::HasFontData() const
     722             : {
     723           0 :   return mSourceType == eSourceType_Buffer && mSourceBuffer;
     724             : }
     725             : 
     726             : void
     727           0 : FontFace::TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength)
     728             : {
     729           0 :   MOZ_ASSERT(HasFontData());
     730             : 
     731           0 :   aBuffer = mSourceBuffer;
     732           0 :   aLength = mSourceBufferLength;
     733             : 
     734           0 :   mSourceBuffer = nullptr;
     735           0 :   mSourceBufferLength = 0;
     736           0 : }
     737             : 
     738             : already_AddRefed<gfxFontFaceBufferSource>
     739           0 : FontFace::CreateBufferSource()
     740             : {
     741           0 :   RefPtr<FontFaceBufferSource> bufferSource = new FontFaceBufferSource(this);
     742           0 :   return bufferSource.forget();
     743             : }
     744             : 
     745             : bool
     746           0 : FontFace::IsInFontFaceSet(FontFaceSet* aFontFaceSet) const
     747             : {
     748           0 :   if (mFontFaceSet == aFontFaceSet) {
     749           0 :     return mInFontFaceSet;
     750             :   }
     751           0 :   return mOtherFontFaceSets.Contains(aFontFaceSet);
     752             : }
     753             : 
     754             : void
     755           0 : FontFace::AddFontFaceSet(FontFaceSet* aFontFaceSet)
     756             : {
     757           0 :   MOZ_ASSERT(!IsInFontFaceSet(aFontFaceSet));
     758             : 
     759           0 :   if (mFontFaceSet == aFontFaceSet) {
     760           0 :     mInFontFaceSet = true;
     761             :   } else {
     762           0 :     mOtherFontFaceSets.AppendElement(aFontFaceSet);
     763             :   }
     764           0 : }
     765             : 
     766             : void
     767           0 : FontFace::RemoveFontFaceSet(FontFaceSet* aFontFaceSet)
     768             : {
     769           0 :   MOZ_ASSERT(IsInFontFaceSet(aFontFaceSet));
     770             : 
     771           0 :   if (mFontFaceSet == aFontFaceSet) {
     772           0 :     mInFontFaceSet = false;
     773             :   } else {
     774           0 :     mOtherFontFaceSets.RemoveElement(aFontFaceSet);
     775             :   }
     776           0 : }
     777             : 
     778             : void
     779           0 : FontFace::Reject(nsresult aResult)
     780             : {
     781           0 :   AssertIsMainThreadOrServoFontMetricsLocked();
     782             : 
     783           0 :   if (mLoaded) {
     784           0 :     DoReject(aResult);
     785           0 :   } else if (mLoadedRejection == NS_OK) {
     786           0 :     mLoadedRejection = aResult;
     787             :   }
     788           0 : }
     789             : 
     790             : void
     791           0 : FontFace::EnsurePromise()
     792             : {
     793           0 :   MOZ_ASSERT(NS_IsMainThread());
     794             : 
     795           0 :   if (mLoaded) {
     796           0 :     return;
     797             :   }
     798             : 
     799           0 :   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
     800             : 
     801             :   // If the pref is not set, don't create the Promise (which the page wouldn't
     802             :   // be able to get to anyway) as it causes the window.FontFace constructor
     803             :   // to be created.
     804           0 :   if (global && FontFaceSet::PrefEnabled()) {
     805           0 :     ErrorResult rv;
     806           0 :     mLoaded = Promise::Create(global, rv);
     807             : 
     808           0 :     if (mStatus == FontFaceLoadStatus::Loaded) {
     809           0 :       mLoaded->MaybeResolve(this);
     810           0 :     } else if (mLoadedRejection != NS_OK) {
     811           0 :       mLoaded->MaybeReject(mLoadedRejection);
     812             :     }
     813             :   }
     814             : }
     815             : 
     816             : gfxCharacterMap*
     817           0 : FontFace::GetUnicodeRangeAsCharacterMap()
     818             : {
     819           0 :   if (!mUnicodeRangeDirty) {
     820           0 :     return mUnicodeRange;
     821             :   }
     822             : 
     823           0 :   nsCSSValue val;
     824           0 :   GetDesc(eCSSFontDesc_UnicodeRange, val);
     825             : 
     826           0 :   if (val.GetUnit() == eCSSUnit_Array) {
     827           0 :     mUnicodeRange = new gfxCharacterMap();
     828           0 :     const nsCSSValue::Array& sources = *val.GetArrayValue();
     829           0 :     MOZ_ASSERT(sources.Count() % 2 == 0,
     830             :                "odd number of entries in a unicode-range: array");
     831             : 
     832           0 :     for (uint32_t i = 0; i < sources.Count(); i += 2) {
     833           0 :       uint32_t min = sources[i].GetIntValue();
     834           0 :       uint32_t max = sources[i+1].GetIntValue();
     835           0 :       mUnicodeRange->SetRange(min, max);
     836             :     }
     837             :   } else {
     838           0 :     mUnicodeRange = nullptr;
     839             :   }
     840             : 
     841           0 :   mUnicodeRangeDirty = false;
     842           0 :   return mUnicodeRange;
     843             : }
     844             : 
     845             : // -- FontFace::Entry --------------------------------------------------------
     846             : 
     847             : /* virtual */ void
     848           0 : FontFace::Entry::SetLoadState(UserFontLoadState aLoadState)
     849             : {
     850           0 :   gfxUserFontEntry::SetLoadState(aLoadState);
     851             : 
     852           0 :   for (size_t i = 0; i < mFontFaces.Length(); i++) {
     853           0 :     mFontFaces[i]->SetStatus(LoadStateToStatus(aLoadState));
     854             :   }
     855           0 : }
     856             : 
     857             : /* virtual */ void
     858           0 : FontFace::Entry::GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult)
     859             : {
     860           0 :   aResult.Clear();
     861             : 
     862           0 :   for (FontFace* f : mFontFaces) {
     863           0 :     if (f->mInFontFaceSet) {
     864           0 :       aResult.AppendElement(f->mFontFaceSet->GetUserFontSet());
     865             :     }
     866           0 :     for (FontFaceSet* s : f->mOtherFontFaceSets) {
     867           0 :       aResult.AppendElement(s->GetUserFontSet());
     868             :     }
     869             :   }
     870             : 
     871             :   // Remove duplicates.
     872           0 :   aResult.Sort();
     873           0 :   auto it = std::unique(aResult.begin(), aResult.end());
     874           0 :   aResult.TruncateLength(it - aResult.begin());
     875           0 : }
     876             : 
     877             : } // namespace dom
     878             : } // namespace mozilla

Generated by: LCOV version 1.13