FontFace.cpp 21 KB

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