2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2014-10-02 06:32:05 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "FontFaceSet.h"
|
|
|
|
|
2015-06-27 04:41:10 +03:00
|
|
|
#include "gfxFontConstants.h"
|
2017-07-08 13:00:24 +03:00
|
|
|
#include "gfxFontSrcPrincipal.h"
|
2017-07-08 09:10:05 +03:00
|
|
|
#include "gfxFontSrcURI.h"
|
2014-10-02 06:32:09 +04:00
|
|
|
#include "mozilla/css/Loader.h"
|
2018-04-20 07:49:29 +03:00
|
|
|
#include "mozilla/dom/Event.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "mozilla/dom/FontFaceSetBinding.h"
|
2015-03-31 06:05:33 +03:00
|
|
|
#include "mozilla/dom/FontFaceSetIterator.h"
|
2015-08-11 05:19:52 +03:00
|
|
|
#include "mozilla/dom/FontFaceSetLoadEvent.h"
|
|
|
|
#include "mozilla/dom/FontFaceSetLoadEventBinding.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "mozilla/dom/Promise.h"
|
2018-04-13 22:34:37 +03:00
|
|
|
#include "mozilla/FontPropertyTypes.h"
|
2017-10-01 04:52:00 +03:00
|
|
|
#include "mozilla/net/ReferrerPolicy.h"
|
2014-10-02 06:32:09 +04:00
|
|
|
#include "mozilla/AsyncEventDispatcher.h"
|
2015-06-27 04:41:10 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2014-10-04 14:36:05 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2017-12-01 12:35:47 +03:00
|
|
|
#include "mozilla/ServoCSSParser.h"
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
#include "mozilla/ServoFontFaceRule.h"
|
2017-04-30 09:55:22 +03:00
|
|
|
#include "mozilla/ServoStyleSet.h"
|
|
|
|
#include "mozilla/ServoUtils.h"
|
2016-08-15 09:43:21 +03:00
|
|
|
#include "mozilla/Sprintf.h"
|
2018-03-20 02:56:37 +03:00
|
|
|
#include "mozilla/StaticPrefs.h"
|
2015-11-25 08:48:16 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2018-03-29 13:16:23 +03:00
|
|
|
#include "mozilla/LoadInfo.h"
|
2016-06-07 23:10:18 +03:00
|
|
|
#include "nsAutoPtr.h"
|
2016-03-02 00:06:13 +03:00
|
|
|
#include "nsContentPolicyUtils.h"
|
2015-06-27 04:41:10 +03:00
|
|
|
#include "nsDeviceContext.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "nsFontFaceLoader.h"
|
|
|
|
#include "nsIConsoleService.h"
|
|
|
|
#include "nsIContentPolicy.h"
|
|
|
|
#include "nsIContentSecurityPolicy.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocument.h"
|
2017-03-24 22:27:11 +03:00
|
|
|
#include "nsILoadContext.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "nsINetworkPredictor.h"
|
|
|
|
#include "nsIPresShell.h"
|
2018-01-31 13:12:36 +03:00
|
|
|
#include "nsIPresShellInlines.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "nsIPrincipal.h"
|
|
|
|
#include "nsISupportsPriority.h"
|
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "nsNetUtil.h"
|
2015-07-07 05:17:00 +03:00
|
|
|
#include "nsIProtocolHandler.h"
|
|
|
|
#include "nsIInputStream.h"
|
2017-11-20 07:43:21 +03:00
|
|
|
#include "nsLayoutUtils.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsPrintfCString.h"
|
2015-06-27 04:41:10 +03:00
|
|
|
#include "nsUTF8Utils.h"
|
2015-11-25 08:48:16 +03:00
|
|
|
#include "nsDOMNavigationTiming.h"
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
using namespace mozilla;
|
2015-06-27 04:41:10 +03:00
|
|
|
using namespace mozilla::css;
|
2014-10-02 06:32:05 +04:00
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
#define LOG(args) MOZ_LOG(gfxUserFontSet::GetUserFontsLog(), mozilla::LogLevel::Debug, args)
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_ENABLED() MOZ_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug)
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-11-11 06:53:55 +03:00
|
|
|
#define FONT_LOADING_API_ENABLED_PREF "layout.css.font-loading-api.enabled"
|
|
|
|
|
2014-10-02 06:32:06 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(FontFaceSet)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FontFaceSet, DOMEventTargetHelper)
|
2014-10-02 06:32:09 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument);
|
2014-10-02 06:32:06 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReady);
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < tmp->mRuleFaces.Length(); i++) {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleFaces[i].mFontFace);
|
2014-10-02 06:32:06 +04:00
|
|
|
}
|
2015-03-27 13:05:22 +03:00
|
|
|
for (size_t i = 0; i < tmp->mNonRuleFaces.Length(); i++) {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNonRuleFaces[i].mFontFace);
|
|
|
|
}
|
2015-05-09 07:48:04 +03:00
|
|
|
if (tmp->mUserFontSet) {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUserFontSet->mFontFaceSet);
|
|
|
|
}
|
2014-10-02 06:32:06 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FontFaceSet, DOMEventTargetHelper)
|
2014-10-02 06:32:09 +04:00
|
|
|
tmp->Disconnect();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument);
|
2014-10-02 06:32:06 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReady);
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < tmp->mRuleFaces.Length(); i++) {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRuleFaces[i].mFontFace);
|
2014-10-02 06:32:06 +04:00
|
|
|
}
|
2015-03-27 13:05:22 +03:00
|
|
|
for (size_t i = 0; i < tmp->mNonRuleFaces.Length(); i++) {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNonRuleFaces[i].mFontFace);
|
|
|
|
}
|
2015-05-09 07:48:04 +03:00
|
|
|
if (tmp->mUserFontSet) {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mUserFontSet->mFontFaceSet);
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mUserFontSet);
|
2014-10-02 06:32:06 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
NS_IMPL_ADDREF_INHERITED(FontFaceSet, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(FontFaceSet, DOMEventTargetHelper)
|
2014-10-02 06:32:06 +04:00
|
|
|
|
2017-08-30 02:02:48 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FontFaceSet)
|
2014-10-02 06:32:09 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
|
2014-10-02 06:32:05 +04:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
FontFaceSet::FontFaceSet(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument)
|
2014-10-02 06:32:05 +04:00
|
|
|
: DOMEventTargetHelper(aWindow)
|
2015-06-27 04:39:54 +03:00
|
|
|
, mDocument(aDocument)
|
2018-03-23 18:06:56 +03:00
|
|
|
, mStandardFontLoadPrincipal(new gfxFontSrcPrincipal(mDocument->NodePrincipal()))
|
2016-10-13 22:08:53 +03:00
|
|
|
, mResolveLazilyCreatedReadyPromise(false)
|
2014-10-02 06:32:09 +04:00
|
|
|
, mStatus(FontFaceSetLoadStatus::Loaded)
|
2014-10-02 06:32:10 +04:00
|
|
|
, mNonRuleFacesDirty(false)
|
2014-10-02 06:32:09 +04:00
|
|
|
, mHasLoadingFontFaces(false)
|
|
|
|
, mHasLoadingFontFacesIsDirty(false)
|
2015-03-27 13:05:22 +03:00
|
|
|
, mDelayedLoadCheck(false)
|
2017-07-05 12:33:46 +03:00
|
|
|
, mBypassCache(false)
|
2017-07-05 12:41:01 +03:00
|
|
|
, mPrivateBrowsing(false)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2017-03-09 13:02:01 +03:00
|
|
|
MOZ_ASSERT(mDocument, "We should get a valid document from the caller!");
|
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
mStandardFontLoadPrincipal =
|
|
|
|
new gfxFontSrcPrincipal(mDocument->NodePrincipal());
|
|
|
|
|
2014-11-11 06:53:55 +03:00
|
|
|
// If the pref is not set, don't create the Promise (which the page wouldn't
|
|
|
|
// be able to get to anyway) as it causes the window.FontFaceSet constructor
|
|
|
|
// to be created.
|
2018-02-23 01:28:39 +03:00
|
|
|
if (aWindow && PrefEnabled()) {
|
2016-10-13 22:08:53 +03:00
|
|
|
mResolveLazilyCreatedReadyPromise = true;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2017-07-05 12:33:46 +03:00
|
|
|
// Record the state of the "bypass cache" flags from the docshell now,
|
|
|
|
// since we want to look at them from style worker threads, and we can
|
|
|
|
// only get to the docshell through a weak pointer (which is only
|
|
|
|
// possible on the main thread).
|
|
|
|
//
|
|
|
|
// In theory the load type of a docshell could change after the document
|
|
|
|
// is loaded, but handling that doesn't seem too important.
|
|
|
|
if (nsCOMPtr<nsIDocShell> docShell = mDocument->GetDocShell()) {
|
|
|
|
uint32_t loadType;
|
|
|
|
uint32_t flags;
|
|
|
|
if ((NS_SUCCEEDED(docShell->GetLoadType(&loadType)) &&
|
|
|
|
((loadType >> 16) & nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE)) ||
|
|
|
|
(NS_SUCCEEDED(docShell->GetDefaultLoadFlags(&flags)) &&
|
|
|
|
(flags & nsIRequest::LOAD_BYPASS_CACHE))) {
|
|
|
|
mBypassCache = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-05 12:41:01 +03:00
|
|
|
// Same for the "private browsing" flag.
|
|
|
|
if (nsCOMPtr<nsILoadContext> loadContext = mDocument->GetLoadContext()) {
|
|
|
|
mPrivateBrowsing = loadContext->UsePrivateBrowsing();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
if (!mDocument->DidFireDOMContentLoaded()) {
|
|
|
|
mDocument->AddSystemEventListener(NS_LITERAL_STRING("DOMContentLoaded"),
|
|
|
|
this, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
mDocument->CSSLoader()->AddObserver(this);
|
2015-05-09 07:46:49 +03:00
|
|
|
|
|
|
|
mUserFontSet = new UserFontSet(this);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
FontFaceSet::~FontFaceSet()
|
|
|
|
{
|
2017-04-30 09:55:22 +03:00
|
|
|
// Assert that we don't drop any FontFaceSet objects during a Servo traversal,
|
|
|
|
// since PostTraversalTask objects can hold raw pointers to FontFaceSets.
|
|
|
|
MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
Disconnect();
|
2015-07-14 03:13:32 +03:00
|
|
|
for (auto it = mLoaders.Iter(); !it.Done(); it.Next()) {
|
|
|
|
it.Get()->GetKey()->Cancel();
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
FontFaceSet::WrapObject(JSContext* aContext, JS::Handle<JSObject*> aGivenProto)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
return FontFaceSetBinding::Wrap(aContext, this, aGivenProto);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
void
|
|
|
|
FontFaceSet::Disconnect()
|
|
|
|
{
|
2015-05-13 08:06:52 +03:00
|
|
|
RemoveDOMContentLoadedListener();
|
|
|
|
|
|
|
|
if (mDocument && mDocument->CSSLoader()) {
|
2014-10-02 06:32:09 +04:00
|
|
|
// We're null checking CSSLoader() since FontFaceSet::Disconnect() might be
|
|
|
|
// being called during unlink, at which time the loader amy already have
|
|
|
|
// been unlinked from the document.
|
2015-05-13 08:06:52 +03:00
|
|
|
mDocument->CSSLoader()->RemoveObserver(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::RemoveDOMContentLoadedListener()
|
|
|
|
{
|
|
|
|
if (mDocument) {
|
|
|
|
mDocument->RemoveSystemEventListener(NS_LITERAL_STRING("DOMContentLoaded"),
|
|
|
|
this, false);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-27 04:41:10 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::ParseFontShorthandForMatching(
|
|
|
|
const nsAString& aFont,
|
2017-10-02 05:24:25 +03:00
|
|
|
RefPtr<SharedFontList>& aFamilyList,
|
2018-04-13 22:34:37 +03:00
|
|
|
FontWeight& aWeight,
|
2018-04-23 17:52:20 +03:00
|
|
|
FontStretch& aStretch,
|
|
|
|
FontSlantStyle& aStyle,
|
2015-06-27 04:41:10 +03:00
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
2018-03-25 20:42:10 +03:00
|
|
|
nsCSSValue style;
|
|
|
|
nsCSSValue stretch;
|
|
|
|
nsCSSValue weight;
|
2018-04-23 17:52:20 +03:00
|
|
|
|
|
|
|
// FIXME(emilio): This Servo -> nsCSSValue -> Gecko conversion is stupid,
|
|
|
|
// Servo understands the font types.
|
2018-03-25 20:42:10 +03:00
|
|
|
RefPtr<URLExtraData> url = ServoCSSParser::GetURLExtraData(mDocument);
|
|
|
|
if (!ServoCSSParser::ParseFontShorthandForMatching(
|
|
|
|
aFont, url, aFamilyList, style, stretch, weight)) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
2017-12-05 08:51:05 +03:00
|
|
|
return;
|
|
|
|
}
|
2018-04-23 17:52:20 +03:00
|
|
|
|
|
|
|
switch (style.GetUnit()) {
|
|
|
|
case eCSSUnit_Normal:
|
|
|
|
aStyle = FontSlantStyle::Normal();
|
|
|
|
break;
|
|
|
|
case eCSSUnit_Enumerated:
|
|
|
|
MOZ_ASSERT(style.GetIntValue() == NS_FONT_STYLE_ITALIC);
|
|
|
|
aStyle = FontSlantStyle::Italic();
|
|
|
|
break;
|
|
|
|
case eCSSUnit_FontSlantStyle:
|
|
|
|
aStyle = style.GetFontSlantStyle();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown unit for font-style");
|
|
|
|
}
|
|
|
|
|
2018-04-13 22:34:37 +03:00
|
|
|
if (weight.GetUnit() == eCSSUnit_FontWeight) {
|
|
|
|
aWeight = weight.GetFontWeight();
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(weight.GetUnit() == eCSSUnit_Enumerated);
|
|
|
|
aWeight = FontWeight(weight.GetIntValue());
|
|
|
|
}
|
2018-04-23 17:52:20 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(stretch.GetUnit() == eCSSUnit_FontStretch);
|
|
|
|
aStretch = stretch.GetFontStretch();
|
2015-06-27 04:41:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
HasAnyCharacterInUnicodeRange(gfxUserFontEntry* aEntry,
|
|
|
|
const nsAString& aInput)
|
|
|
|
{
|
|
|
|
const char16_t* p = aInput.Data();
|
|
|
|
const char16_t* end = p + aInput.Length();
|
|
|
|
|
|
|
|
while (p < end) {
|
|
|
|
uint32_t c = UTF16CharEnumerator::NextChar(&p, end);
|
|
|
|
if (aEntry->CharacterInUnicodeRange(c)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::FindMatchingFontFaces(const nsAString& aFont,
|
|
|
|
const nsAString& aText,
|
|
|
|
nsTArray<FontFace*>& aFontFaces,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
2017-10-02 05:24:25 +03:00
|
|
|
RefPtr<SharedFontList> familyList;
|
2018-04-13 22:34:37 +03:00
|
|
|
FontWeight weight;
|
2018-04-23 17:52:20 +03:00
|
|
|
FontStretch stretch;
|
|
|
|
FontSlantStyle italicStyle;
|
2015-06-27 04:41:10 +03:00
|
|
|
ParseFontShorthandForMatching(aFont, familyList, weight, stretch, italicStyle,
|
|
|
|
aRv);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxFontStyle style;
|
|
|
|
style.style = italicStyle;
|
|
|
|
style.weight = weight;
|
|
|
|
style.stretch = stretch;
|
|
|
|
|
|
|
|
nsTArray<FontFaceRecord>* arrays[2];
|
|
|
|
arrays[0] = &mNonRuleFaces;
|
|
|
|
arrays[1] = &mRuleFaces;
|
|
|
|
|
|
|
|
// Set of FontFaces that we want to return.
|
|
|
|
nsTHashtable<nsPtrHashKey<FontFace>> matchingFaces;
|
|
|
|
|
2017-10-02 05:24:25 +03:00
|
|
|
for (const FontFamilyName& fontFamilyName : familyList->mNames) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxFontFamily> family =
|
2015-06-27 04:41:10 +03:00
|
|
|
mUserFontSet->LookupFamily(fontFamilyName.mName);
|
|
|
|
|
|
|
|
if (!family) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<gfxFontEntry*,4> entries;
|
2015-06-27 04:41:10 +03:00
|
|
|
bool needsBold;
|
|
|
|
family->FindAllFontsForStyle(style, entries, needsBold);
|
|
|
|
|
|
|
|
for (gfxFontEntry* e : entries) {
|
|
|
|
FontFace::Entry* entry = static_cast<FontFace::Entry*>(e);
|
|
|
|
if (HasAnyCharacterInUnicodeRange(entry, aText)) {
|
|
|
|
for (FontFace* f : entry->GetFontFaces()) {
|
|
|
|
matchingFaces.PutEntry(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add all FontFaces in matchingFaces to aFontFaces, in the order
|
|
|
|
// they appear in the FontFaceSet.
|
|
|
|
for (nsTArray<FontFaceRecord>* array : arrays) {
|
|
|
|
for (FontFaceRecord& record : *array) {
|
|
|
|
FontFace* f = record.mFontFace;
|
|
|
|
if (matchingFaces.Contains(f)) {
|
|
|
|
aFontFaces.AppendElement(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-25 08:48:16 +03:00
|
|
|
TimeStamp
|
|
|
|
FontFaceSet::GetNavigationStartTimeStamp()
|
|
|
|
{
|
|
|
|
TimeStamp navStart;
|
|
|
|
RefPtr<nsDOMNavigationTiming> timing(mDocument->GetNavigationTiming());
|
|
|
|
if (timing) {
|
|
|
|
navStart = timing->GetNavigationStartTimeStamp();
|
|
|
|
}
|
|
|
|
return navStart;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
already_AddRefed<Promise>
|
2015-06-27 04:41:10 +03:00
|
|
|
FontFaceSet::Load(JSContext* aCx,
|
|
|
|
const nsAString& aFont,
|
2014-10-02 06:32:05 +04:00
|
|
|
const nsAString& aText,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:41:10 +03:00
|
|
|
FlushUserFontSet();
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<Promise>> promises;
|
2015-06-27 04:41:10 +03:00
|
|
|
|
|
|
|
nsTArray<FontFace*> faces;
|
|
|
|
FindMatchingFontFaces(aFont, aText, faces, aRv);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (FontFace* f : faces) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Promise> promise = f->Load(aRv);
|
2015-06-27 04:41:10 +03:00
|
|
|
if (aRv.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!promises.AppendElement(promise, fallible)) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-14 02:31:42 +03:00
|
|
|
return Promise::All(aCx, promises, aRv);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
FontFaceSet::Check(const nsAString& aFont,
|
|
|
|
const nsAString& aText,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:41:10 +03:00
|
|
|
FlushUserFontSet();
|
|
|
|
|
|
|
|
nsTArray<FontFace*> faces;
|
|
|
|
FindMatchingFontFaces(aFont, aText, faces, aRv);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (FontFace* f : faces) {
|
|
|
|
if (f->Status() != FontFaceLoadStatus::Loaded) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
Promise*
|
|
|
|
FontFaceSet::GetReady(ErrorResult& aRv)
|
|
|
|
{
|
2017-04-30 09:55:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
if (!mReady) {
|
2016-10-13 22:08:53 +03:00
|
|
|
nsCOMPtr<nsIGlobalObject> global = GetParentObject();
|
|
|
|
mReady = Promise::Create(global, aRv);
|
|
|
|
if (!mReady) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (mResolveLazilyCreatedReadyPromise) {
|
|
|
|
mReady->MaybeResolve(this);
|
|
|
|
mResolveLazilyCreatedReadyPromise = false;
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:05 +04:00
|
|
|
return mReady;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontFaceSetLoadStatus
|
|
|
|
FontFaceSet::Status()
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:09 +04:00
|
|
|
return mStatus;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
bool
|
2014-10-02 06:32:10 +04:00
|
|
|
FontFaceSet::HasRuleFontFace(FontFace* aFontFace)
|
2014-10-02 06:32:08 +04:00
|
|
|
{
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < mRuleFaces.Length(); i++) {
|
|
|
|
if (mRuleFaces[i].mFontFace == aFontFace) {
|
2014-10-02 06:32:08 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-02-01 22:23:34 +03:00
|
|
|
void
|
2014-10-02 06:32:05 +04:00
|
|
|
FontFaceSet::Add(FontFace& aFontFace, ErrorResult& aRv)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
if (aFontFace.IsInFontFaceSet(this)) {
|
2018-02-01 22:23:34 +03:00
|
|
|
return;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
if (aFontFace.HasRule()) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_MODIFICATION_ERR);
|
2018-02-01 22:23:34 +03:00
|
|
|
return;
|
2015-10-16 09:10:14 +03:00
|
|
|
}
|
2015-05-09 07:46:31 +03:00
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
aFontFace.AddFontFaceSet(this);
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-03-27 13:05:22 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
for (const FontFaceRecord& rec : mNonRuleFaces) {
|
|
|
|
MOZ_ASSERT(rec.mFontFace != &aFontFace,
|
|
|
|
"FontFace should not occur in mNonRuleFaces twice");
|
|
|
|
}
|
|
|
|
#endif
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2015-03-27 13:05:22 +03:00
|
|
|
FontFaceRecord* rec = mNonRuleFaces.AppendElement();
|
|
|
|
rec->mFontFace = &aFontFace;
|
2015-10-20 02:16:20 +03:00
|
|
|
rec->mSheetType = SheetType::Unknown; // unused for mNonRuleFaces
|
2015-03-27 13:05:22 +03:00
|
|
|
rec->mLoadEventShouldFire =
|
|
|
|
aFontFace.Status() == FontFaceLoadStatus::Unloaded ||
|
|
|
|
aFontFace.Status() == FontFaceLoadStatus::Loading;
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
mNonRuleFacesDirty = true;
|
2018-01-31 13:12:36 +03:00
|
|
|
MarkUserFontSetDirty();
|
2014-10-02 06:32:09 +04:00
|
|
|
mHasLoadingFontFacesIsDirty = true;
|
|
|
|
CheckLoadingStarted();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::Clear()
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
if (mNonRuleFaces.IsEmpty()) {
|
2014-10-02 06:32:09 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < mNonRuleFaces.Length(); i++) {
|
2015-03-27 13:05:22 +03:00
|
|
|
FontFace* f = mNonRuleFaces[i].mFontFace;
|
2015-10-16 09:10:14 +03:00
|
|
|
f->RemoveFontFaceSet(this);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
mNonRuleFaces.Clear();
|
|
|
|
mNonRuleFacesDirty = true;
|
2018-01-31 13:12:36 +03:00
|
|
|
MarkUserFontSetDirty();
|
2014-10-02 06:32:09 +04:00
|
|
|
mHasLoadingFontFacesIsDirty = true;
|
|
|
|
CheckLoadingFinished();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-05-13 05:24:34 +03:00
|
|
|
FontFaceSet::Delete(FontFace& aFontFace)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
if (aFontFace.HasRule()) {
|
2014-10-04 19:06:21 +04:00
|
|
|
return false;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2015-03-27 13:05:22 +03:00
|
|
|
bool removed = false;
|
|
|
|
for (size_t i = 0; i < mNonRuleFaces.Length(); i++) {
|
|
|
|
if (mNonRuleFaces[i].mFontFace == &aFontFace) {
|
|
|
|
mNonRuleFaces.RemoveElementAt(i);
|
|
|
|
removed = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!removed) {
|
2014-10-02 06:32:09 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-10-16 09:10:14 +03:00
|
|
|
aFontFace.RemoveFontFaceSet(this);
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
mNonRuleFacesDirty = true;
|
2018-01-31 13:12:36 +03:00
|
|
|
MarkUserFontSetDirty();
|
2014-10-02 06:32:09 +04:00
|
|
|
mHasLoadingFontFacesIsDirty = true;
|
|
|
|
CheckLoadingFinished();
|
2014-10-02 06:32:09 +04:00
|
|
|
return true;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
bool
|
|
|
|
FontFaceSet::HasAvailableFontFace(FontFace* aFontFace)
|
|
|
|
{
|
2015-10-16 09:10:14 +03:00
|
|
|
return aFontFace->IsInFontFaceSet(this);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
bool
|
|
|
|
FontFaceSet::Has(FontFace& aFontFace)
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:09 +04:00
|
|
|
|
|
|
|
return HasAvailableFontFace(&aFontFace);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
FontFace*
|
2015-03-31 06:05:33 +03:00
|
|
|
FontFaceSet::GetFontFaceAt(uint32_t aIndex)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:06 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
if (aIndex < mRuleFaces.Length()) {
|
|
|
|
return mRuleFaces[aIndex].mFontFace;
|
2014-10-02 06:32:08 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
aIndex -= mRuleFaces.Length();
|
|
|
|
if (aIndex < mNonRuleFaces.Length()) {
|
2015-03-27 13:05:22 +03:00
|
|
|
return mNonRuleFaces[aIndex].mFontFace;
|
2014-10-02 06:32:06 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
return nullptr;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
2015-03-31 06:05:33 +03:00
|
|
|
FontFaceSet::Size()
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
FlushUserFontSet();
|
2014-10-02 06:32:06 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
// Web IDL objects can only expose array index properties up to INT32_MAX.
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
size_t total = mRuleFaces.Length() + mNonRuleFaces.Length();
|
2014-10-02 06:32:08 +04:00
|
|
|
return std::min<size_t>(total, INT32_MAX);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2015-07-16 10:35:17 +03:00
|
|
|
already_AddRefed<FontFaceSetIterator>
|
2015-03-31 06:05:33 +03:00
|
|
|
FontFaceSet::Entries()
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFaceSetIterator> it = new FontFaceSetIterator(this, true);
|
2015-07-16 10:35:17 +03:00
|
|
|
return it.forget();
|
2015-03-31 06:05:33 +03:00
|
|
|
}
|
|
|
|
|
2015-07-16 10:35:17 +03:00
|
|
|
already_AddRefed<FontFaceSetIterator>
|
2015-03-31 06:05:33 +03:00
|
|
|
FontFaceSet::Values()
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFaceSetIterator> it = new FontFaceSetIterator(this, false);
|
2015-07-16 10:35:17 +03:00
|
|
|
return it.forget();
|
2015-03-31 06:05:33 +03:00
|
|
|
}
|
|
|
|
|
2015-03-31 06:05:33 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::ForEach(JSContext* aCx,
|
|
|
|
FontFaceSetForEachCallback& aCallback,
|
|
|
|
JS::Handle<JS::Value> aThisArg,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
JS::Rooted<JS::Value> thisArg(aCx, aThisArg);
|
|
|
|
for (size_t i = 0; i < Size(); i++) {
|
|
|
|
FontFace* face = GetFontFaceAt(i);
|
|
|
|
aCallback.Call(thisArg, *face, *face, *this, aRv);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
void
|
|
|
|
FontFaceSet::RemoveLoader(nsFontFaceLoader* aLoader)
|
|
|
|
{
|
|
|
|
mLoaders.RemoveEntry(aLoader);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
|
|
|
|
const gfxFontFaceSrc* aFontFaceSrc)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStreamLoader> streamLoader;
|
2015-06-27 04:39:54 +03:00
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup(mDocument->GetDocumentLoadGroup());
|
2017-07-08 13:00:24 +03:00
|
|
|
gfxFontSrcPrincipal* principal = aUserFontEntry->GetPrincipal();
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2014-11-14 19:56:55 +03:00
|
|
|
// Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
|
|
|
|
// node and a principal. This is because the document where the font is
|
|
|
|
// being loaded might have a different origin from the principal of the
|
|
|
|
// stylesheet that initiated the font load.
|
|
|
|
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
|
2017-07-08 09:10:05 +03:00
|
|
|
aFontFaceSrc->mURI->get(),
|
2015-06-27 04:39:54 +03:00
|
|
|
mDocument,
|
2017-07-08 13:00:24 +03:00
|
|
|
principal ? principal->get() : nullptr,
|
2016-03-02 00:06:13 +03:00
|
|
|
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
|
2014-11-14 19:56:55 +03:00
|
|
|
nsIContentPolicy::TYPE_FONT,
|
2018-01-24 19:17:31 +03:00
|
|
|
nullptr, // PerformanceStorage
|
2014-11-14 19:56:55 +03:00
|
|
|
loadGroup);
|
2014-10-02 06:32:05 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFontFaceLoader> fontLoader =
|
2017-07-08 09:10:05 +03:00
|
|
|
new nsFontFaceLoader(aUserFontEntry, aFontFaceSrc->mURI->get(), this,
|
|
|
|
channel);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2015-01-29 10:44:59 +03:00
|
|
|
if (LOG_ENABLED()) {
|
|
|
|
LOG(("userfonts (%p) download start - font uri: (%s) "
|
|
|
|
"referrer uri: (%s)\n",
|
2016-08-26 09:02:31 +03:00
|
|
|
fontLoader.get(), aFontFaceSrc->mURI->GetSpecOrDefault().get(),
|
|
|
|
aFontFaceSrc->mReferrer
|
|
|
|
? aFontFaceSrc->mReferrer->GetSpecOrDefault().get()
|
|
|
|
: ""));
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
2014-10-09 11:42:02 +04:00
|
|
|
if (httpChannel) {
|
2016-12-20 12:19:56 +03:00
|
|
|
rv = httpChannel->SetReferrerWithPolicy(aFontFaceSrc->mReferrer,
|
|
|
|
mDocument->GetReferrerPolicy());
|
2017-04-27 21:34:00 +03:00
|
|
|
Unused << NS_WARN_IF(NS_FAILED(rv));
|
2016-12-20 12:19:56 +03:00
|
|
|
|
2014-10-09 11:42:02 +04:00
|
|
|
nsAutoCString accept("application/font-woff;q=0.9,*/*;q=0.8");
|
|
|
|
if (Preferences::GetBool(GFX_PREF_WOFF2_ENABLED)) {
|
2017-09-08 04:15:42 +03:00
|
|
|
accept.InsertLiteral("application/font-woff2;q=1.0,", 0);
|
2014-10-09 11:42:02 +04:00
|
|
|
}
|
2016-12-20 12:19:56 +03:00
|
|
|
rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
|
|
|
accept, false);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2014-10-09 11:42:51 +04:00
|
|
|
// For WOFF and WOFF2, we should tell servers/proxies/etc NOT to try
|
|
|
|
// and apply additional compression at the content-encoding layer
|
|
|
|
if (aFontFaceSrc->mFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF |
|
|
|
|
gfxUserFontSet::FLAG_FORMAT_WOFF2)) {
|
2016-12-20 12:19:56 +03:00
|
|
|
rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept-Encoding"),
|
|
|
|
NS_LITERAL_CSTRING("identity"), false);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2014-10-09 11:42:51 +04:00
|
|
|
}
|
2014-10-09 11:42:02 +04:00
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
nsCOMPtr<nsISupportsPriority> priorityChannel(do_QueryInterface(channel));
|
|
|
|
if (priorityChannel) {
|
|
|
|
priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGH);
|
|
|
|
}
|
|
|
|
|
2017-09-29 05:10:13 +03:00
|
|
|
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), fontLoader, fontLoader);
|
2014-10-02 06:32:05 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2017-07-08 09:10:05 +03:00
|
|
|
mozilla::net::PredictorLearn(aFontFaceSrc->mURI->get(),
|
|
|
|
mDocument->GetDocumentURI(),
|
2014-10-02 06:32:05 +04:00
|
|
|
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
|
|
|
|
loadGroup);
|
|
|
|
|
2016-03-02 00:06:13 +03:00
|
|
|
rv = channel->AsyncOpen2(streamLoader);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
fontLoader->DropChannel(); // explicitly need to break ref cycle
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
mLoaders.PutEntry(fontLoader);
|
|
|
|
fontLoader->StartedLoading(streamLoader);
|
|
|
|
aUserFontEntry->SetLoader(fontLoader); // let the font entry remember the
|
|
|
|
// loader, in case we need to cancel it
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
FontFaceSet::UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mUserFontSet);
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
// If there was a change to the mNonRuleFaces array, then there could
|
2014-10-02 06:32:08 +04:00
|
|
|
// have been a modification to the user font set.
|
2014-10-02 06:32:10 +04:00
|
|
|
bool modified = mNonRuleFacesDirty;
|
|
|
|
mNonRuleFacesDirty = false;
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-09 11:03:56 +04:00
|
|
|
// reuse existing FontFace objects mapped to rules already
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
nsDataHashtable<nsPtrHashKey<RawServoFontFaceRule>, FontFace*> ruleFaceMap;
|
2014-10-09 11:03:56 +04:00
|
|
|
for (size_t i = 0, i_end = mRuleFaces.Length(); i < i_end; ++i) {
|
|
|
|
FontFace* f = mRuleFaces[i].mFontFace;
|
|
|
|
if (!f) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ruleFaceMap.Put(f->GetRule(), f);
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
// The @font-face rules that make up the user font set have changed,
|
|
|
|
// so we need to update the set. However, we want to preserve existing
|
|
|
|
// font entries wherever possible, so that we don't discard and then
|
|
|
|
// re-download resources in the (common) case where at least some of the
|
|
|
|
// same rules are still present.
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
nsTArray<FontFaceRecord> oldRecords;
|
2014-10-02 06:32:10 +04:00
|
|
|
mRuleFaces.SwapElements(oldRecords);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
// Remove faces from the font family records; we need to re-insert them
|
|
|
|
// because we might end up with faces in a different order even if they're
|
|
|
|
// the same font entries as before. (The order can affect font selection
|
|
|
|
// where multiple faces match the requested style, perhaps with overlapping
|
|
|
|
// unicode-range coverage.)
|
2015-11-23 08:08:22 +03:00
|
|
|
for (auto it = mUserFontSet->mFontFamilies.Iter(); !it.Done(); it.Next()) {
|
|
|
|
it.Data()->DetachFontEntries();
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
// Sometimes aRules has duplicate @font-face rules in it; we should make
|
|
|
|
// that not happen, but in the meantime, don't try to insert the same
|
2014-10-02 06:32:10 +04:00
|
|
|
// FontFace object more than once into mRuleFaces. We track which
|
2014-10-02 06:32:08 +04:00
|
|
|
// ones we've handled in this table.
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
nsTHashtable<nsPtrHashKey<RawServoFontFaceRule>> handledRules;
|
2014-10-02 06:32:08 +04:00
|
|
|
|
|
|
|
for (size_t i = 0, i_end = aRules.Length(); i < i_end; ++i) {
|
2014-10-02 06:32:07 +04:00
|
|
|
// Insert each FontFace objects for each rule into our list, migrating old
|
|
|
|
// font entries if possible rather than creating new ones; set modified to
|
|
|
|
// true if we detect that rule ordering has changed, or if a new entry is
|
|
|
|
// created.
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
RawServoFontFaceRule* rule = aRules[i].mRule;
|
2017-06-17 01:06:04 +03:00
|
|
|
if (!handledRules.EnsureInserted(rule)) {
|
|
|
|
// rule was already present in the hashtable
|
2014-10-02 06:32:08 +04:00
|
|
|
continue;
|
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFace> f = ruleFaceMap.Get(rule);
|
2014-10-09 11:03:56 +04:00
|
|
|
if (!f.get()) {
|
2015-06-27 04:39:54 +03:00
|
|
|
f = FontFace::CreateForRule(GetParentObject(), this, rule);
|
2014-10-09 11:03:56 +04:00
|
|
|
}
|
|
|
|
InsertRuleFontFace(f, aRules[i].mSheetType, oldRecords, modified);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0, i_end = mNonRuleFaces.Length(); i < i_end; ++i) {
|
|
|
|
// Do the same for the non rule backed FontFace objects.
|
2015-03-27 13:05:22 +03:00
|
|
|
InsertNonRuleFontFace(mNonRuleFaces[i].mFontFace, modified);
|
2014-10-02 06:32:08 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
// Remove any residual families that have no font entries (i.e., they were
|
|
|
|
// not defined at all by the updated set of @font-face rules).
|
2015-11-23 08:08:22 +03:00
|
|
|
for (auto it = mUserFontSet->mFontFamilies.Iter(); !it.Done(); it.Next()) {
|
|
|
|
if (it.Data()->GetFontList().IsEmpty()) {
|
|
|
|
it.Remove();
|
|
|
|
}
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:07 +04:00
|
|
|
// If any FontFace objects for rules are left in the old list, note that the
|
|
|
|
// set has changed (even if the new set was built entirely by migrating old
|
|
|
|
// font entries).
|
|
|
|
if (oldRecords.Length() > 0) {
|
2014-10-02 06:32:05 +04:00
|
|
|
modified = true;
|
|
|
|
// Any in-progress loaders for obsolete rules should be cancelled,
|
|
|
|
// as the resource being downloaded will no longer be required.
|
|
|
|
// We need to explicitly remove any loaders here, otherwise the loaders
|
|
|
|
// will keep their "orphaned" font entries alive until they complete,
|
|
|
|
// even after the oldRules array is deleted.
|
2014-10-02 06:32:07 +04:00
|
|
|
//
|
2014-10-02 06:32:10 +04:00
|
|
|
// XXX Now that it is possible for the author to hold on to a rule backed
|
2014-10-02 06:32:07 +04:00
|
|
|
// FontFace object, we shouldn't cancel loading here; instead we should do
|
|
|
|
// it when the FontFace is GCed, if we can detect that.
|
|
|
|
size_t count = oldRecords.Length();
|
2014-10-02 06:32:05 +04:00
|
|
|
for (size_t i = 0; i < count; ++i) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFace> f = oldRecords[i].mFontFace;
|
2014-10-02 06:32:08 +04:00
|
|
|
gfxUserFontEntry* userFontEntry = f->GetUserFontEntry();
|
2014-10-02 06:32:08 +04:00
|
|
|
if (userFontEntry) {
|
|
|
|
nsFontFaceLoader* loader = userFontEntry->GetLoader();
|
|
|
|
if (loader) {
|
|
|
|
loader->Cancel();
|
|
|
|
RemoveLoader(loader);
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
2014-10-02 06:32:08 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
// Any left over FontFace objects should also cease being rule backed.
|
2014-10-09 11:03:28 +04:00
|
|
|
f->DisconnectFromRule();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modified) {
|
|
|
|
IncrementGeneration(true);
|
2014-10-02 06:32:09 +04:00
|
|
|
mHasLoadingFontFacesIsDirty = true;
|
|
|
|
CheckLoadingStarted();
|
|
|
|
CheckLoadingFinished();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2016-02-08 04:11:39 +03:00
|
|
|
// if local rules needed to be rebuilt, they have been rebuilt at this point
|
|
|
|
if (mUserFontSet->mRebuildLocalRules) {
|
|
|
|
mUserFontSet->mLocalRulesUsed = false;
|
|
|
|
mUserFontSet->mRebuildLocalRules = false;
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2015-01-29 10:44:59 +03:00
|
|
|
if (LOG_ENABLED() && !mRuleFaces.IsEmpty()) {
|
2016-01-14 10:11:47 +03:00
|
|
|
LOG(("userfonts (%p) userfont rules update (%s) rule count: %d",
|
2015-01-29 10:44:59 +03:00
|
|
|
mUserFontSet.get(),
|
|
|
|
(modified ? "modified" : "not modified"),
|
2016-01-14 10:11:47 +03:00
|
|
|
(int)(mRuleFaces.Length())));
|
2015-01-29 10:44:59 +03:00
|
|
|
}
|
2014-10-17 04:15:29 +04:00
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
return modified;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
HasLocalSrc(const nsCSSValue::Array *aSrcArr)
|
|
|
|
{
|
|
|
|
size_t numSrc = aSrcArr->Count();
|
|
|
|
for (size_t i = 0; i < numSrc; i++) {
|
|
|
|
if (aSrcArr->Item(i).GetUnit() == eCSSUnit_Local_Font) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::IncrementGeneration(bool aIsRebuild)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mUserFontSet);
|
|
|
|
mUserFontSet->IncrementGeneration(aIsRebuild);
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
void
|
2014-10-02 06:32:10 +04:00
|
|
|
FontFaceSet::InsertNonRuleFontFace(FontFace* aFontFace,
|
|
|
|
bool& aFontSetModified)
|
2014-10-02 06:32:08 +04:00
|
|
|
{
|
|
|
|
nsAutoString fontfamily;
|
|
|
|
if (!aFontFace->GetFamilyName(fontfamily)) {
|
|
|
|
// If there is no family name, this rule cannot contribute a
|
|
|
|
// usable font, so there is no point in processing it further.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just create a new font entry if we haven't got one already.
|
|
|
|
if (!aFontFace->GetUserFontEntry()) {
|
|
|
|
// XXX Should we be checking mUserFontSet->mLocalRulesUsed like
|
2014-10-02 06:32:10 +04:00
|
|
|
// InsertRuleFontFace does?
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxUserFontEntry> entry =
|
2014-10-02 06:32:08 +04:00
|
|
|
FindOrCreateUserFontEntryFromFontFace(fontfamily, aFontFace,
|
2015-10-20 02:16:20 +03:00
|
|
|
SheetType::Doc);
|
2014-10-02 06:32:08 +04:00
|
|
|
if (!entry) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
aFontFace->SetUserFontEntry(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
aFontSetModified = true;
|
|
|
|
mUserFontSet->AddUserFontEntry(fontfamily, aFontFace->GetUserFontEntry());
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
void
|
2015-10-20 02:16:20 +03:00
|
|
|
FontFaceSet::InsertRuleFontFace(FontFace* aFontFace, SheetType aSheetType,
|
2014-10-02 06:32:10 +04:00
|
|
|
nsTArray<FontFaceRecord>& aOldRecords,
|
|
|
|
bool& aFontSetModified)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
|
|
|
nsAutoString fontfamily;
|
2014-10-02 06:32:08 +04:00
|
|
|
if (!aFontFace->GetFamilyName(fontfamily)) {
|
2014-10-02 06:32:05 +04:00
|
|
|
// If there is no family name, this rule cannot contribute a
|
|
|
|
// usable font, so there is no point in processing it further.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
bool remove = false;
|
|
|
|
size_t removeIndex;
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
// This is a rule backed FontFace. First, we check in aOldRecords; if
|
2014-10-02 06:32:08 +04:00
|
|
|
// the FontFace for the rule exists there, just move it to the new record
|
|
|
|
// list, and put the entry into the appropriate family.
|
|
|
|
for (size_t i = 0; i < aOldRecords.Length(); ++i) {
|
|
|
|
FontFaceRecord& rec = aOldRecords[i];
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
if (rec.mFontFace == aFontFace &&
|
2014-10-02 06:32:07 +04:00
|
|
|
rec.mSheetType == aSheetType) {
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
// if local rules were used, don't use the old font entry
|
|
|
|
// for rules containing src local usage
|
2016-02-08 04:11:39 +03:00
|
|
|
if (mUserFontSet->mLocalRulesUsed &&
|
|
|
|
mUserFontSet->mRebuildLocalRules) {
|
2014-10-02 06:32:08 +04:00
|
|
|
nsCSSValue val;
|
|
|
|
aFontFace->GetDesc(eCSSFontDesc_Src, val);
|
|
|
|
nsCSSUnit unit = val.GetUnit();
|
2014-10-02 06:32:05 +04:00
|
|
|
if (unit == eCSSUnit_Array && HasLocalSrc(val.GetArrayValue())) {
|
2014-10-02 06:32:08 +04:00
|
|
|
// Remove the old record, but wait to see if we successfully create a
|
|
|
|
// new user font entry below.
|
|
|
|
remove = true;
|
|
|
|
removeIndex = i;
|
2014-10-02 06:32:05 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
gfxUserFontEntry* entry = rec.mFontFace->GetUserFontEntry();
|
|
|
|
MOZ_ASSERT(entry, "FontFace should have a gfxUserFontEntry by now");
|
2014-10-02 06:32:08 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
mUserFontSet->AddUserFontEntry(fontfamily, entry);
|
2014-10-02 06:32:08 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
MOZ_ASSERT(!HasRuleFontFace(rec.mFontFace),
|
|
|
|
"FontFace should not occur in mRuleFaces twice");
|
2014-10-02 06:32:08 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
mRuleFaces.AppendElement(rec);
|
2014-10-02 06:32:07 +04:00
|
|
|
aOldRecords.RemoveElementAt(i);
|
2014-10-02 06:32:05 +04:00
|
|
|
// note the set has been modified if an old rule was skipped to find
|
|
|
|
// this one - something has been dropped, or ordering changed
|
|
|
|
if (i > 0) {
|
|
|
|
aFontSetModified = true;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// this is a new rule:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxUserFontEntry> entry =
|
2014-10-02 06:32:08 +04:00
|
|
|
FindOrCreateUserFontEntryFromFontFace(fontfamily, aFontFace, aSheetType);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
if (!entry) {
|
2014-10-02 06:32:05 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
if (remove) {
|
|
|
|
// Although we broke out of the aOldRecords loop above, since we found
|
|
|
|
// src local usage, and we're not using the old user font entry, we still
|
2014-10-02 06:32:10 +04:00
|
|
|
// are adding a record to mRuleFaces with the same FontFace object.
|
2014-10-02 06:32:08 +04:00
|
|
|
// Remove the old record so that we don't have the same FontFace listed
|
2014-10-02 06:32:10 +04:00
|
|
|
// in both mRuleFaces and oldRecords, which would cause us to call
|
|
|
|
// DisconnectFromRule on a FontFace that should still be rule backed.
|
2014-10-02 06:32:08 +04:00
|
|
|
aOldRecords.RemoveElementAt(removeIndex);
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
FontFaceRecord rec;
|
2014-10-02 06:32:08 +04:00
|
|
|
rec.mFontFace = aFontFace;
|
2014-10-02 06:32:07 +04:00
|
|
|
rec.mSheetType = aSheetType;
|
2015-03-27 13:05:22 +03:00
|
|
|
rec.mLoadEventShouldFire =
|
|
|
|
aFontFace->Status() == FontFaceLoadStatus::Unloaded ||
|
|
|
|
aFontFace->Status() == FontFaceLoadStatus::Loading;
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:08 +04:00
|
|
|
aFontFace->SetUserFontEntry(entry);
|
2014-10-02 06:32:08 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
MOZ_ASSERT(!HasRuleFontFace(aFontFace),
|
|
|
|
"FontFace should not occur in mRuleFaces twice");
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
mRuleFaces.AppendElement(rec);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
// this was a new rule and font entry, so note that the set was modified
|
|
|
|
aFontSetModified = true;
|
2014-10-02 06:32:08 +04:00
|
|
|
|
|
|
|
// Add the entry to the end of the list. If an existing userfont entry was
|
|
|
|
// returned by FindOrCreateUserFontEntryFromFontFace that was already stored
|
|
|
|
// on the family, gfxUserFontFamily::AddFontEntry(), which AddUserFontEntry
|
|
|
|
// calls, will automatically remove the earlier occurrence of the same
|
|
|
|
// userfont entry.
|
|
|
|
mUserFontSet->AddUserFontEntry(fontfamily, entry);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2017-12-21 22:07:31 +03:00
|
|
|
/* static */ already_AddRefed<gfxUserFontEntry>
|
2014-10-02 06:32:09 +04:00
|
|
|
FontFaceSet::FindOrCreateUserFontEntryFromFontFace(FontFace* aFontFace)
|
|
|
|
{
|
|
|
|
nsAutoString fontfamily;
|
|
|
|
if (!aFontFace->GetFamilyName(fontfamily)) {
|
|
|
|
// If there is no family name, this rule cannot contribute a
|
|
|
|
// usable font, so there is no point in processing it further.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FindOrCreateUserFontEntryFromFontFace(fontfamily, aFontFace,
|
2015-10-20 02:16:20 +03:00
|
|
|
SheetType::Doc);
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2018-04-17 14:30:04 +03:00
|
|
|
static FontWeight
|
|
|
|
GetWeightForDescriptor(const nsCSSValue& aVal)
|
|
|
|
{
|
|
|
|
switch (aVal.GetUnit()) {
|
|
|
|
case eCSSUnit_FontWeight:
|
|
|
|
return aVal.GetFontWeight();
|
|
|
|
case eCSSUnit_Enumerated:
|
|
|
|
return FontWeight(aVal.GetIntValue());
|
|
|
|
case eCSSUnit_Normal:
|
|
|
|
case eCSSUnit_Null:
|
|
|
|
return FontWeight::Normal();
|
2018-04-25 12:18:07 +03:00
|
|
|
case eCSSUnit_Pair:
|
|
|
|
// TODO(jfkthame): Handle optional second value of the font descriptor.
|
|
|
|
return GetWeightForDescriptor(aVal.GetPairValue().mXValue);
|
2018-04-17 14:30:04 +03:00
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown font-weight descriptor value");
|
|
|
|
return FontWeight::Normal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-23 17:52:20 +03:00
|
|
|
static FontSlantStyle
|
|
|
|
GetStyleForDescriptor(const nsCSSValue& aVal)
|
|
|
|
{
|
|
|
|
switch (aVal.GetUnit()) {
|
|
|
|
case eCSSUnit_Normal:
|
|
|
|
case eCSSUnit_Null:
|
|
|
|
return FontSlantStyle::Normal();
|
|
|
|
case eCSSUnit_Enumerated:
|
|
|
|
MOZ_ASSERT(aVal.GetIntValue() == NS_FONT_STYLE_ITALIC);
|
|
|
|
return FontSlantStyle::Italic();
|
|
|
|
case eCSSUnit_FontSlantStyle:
|
|
|
|
return aVal.GetFontSlantStyle();
|
2018-04-25 12:18:07 +03:00
|
|
|
case eCSSUnit_Pair:
|
|
|
|
// TODO(jfkthame): Handle optional second value of the font descriptor.
|
|
|
|
return GetStyleForDescriptor(aVal.GetPairValue().mXValue);
|
2018-04-23 17:52:20 +03:00
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown font-style descriptor value");
|
|
|
|
return FontSlantStyle::Normal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static FontStretch
|
|
|
|
GetStretchForDescriptor(const nsCSSValue& aVal)
|
|
|
|
{
|
|
|
|
switch (aVal.GetUnit()) {
|
|
|
|
case eCSSUnit_Null:
|
|
|
|
return FontStretch::Normal();
|
|
|
|
case eCSSUnit_FontStretch:
|
|
|
|
return aVal.GetFontStretch();
|
2018-04-25 12:18:07 +03:00
|
|
|
case eCSSUnit_Pair:
|
|
|
|
// TODO(jfkthame): Handle optional second value of the font descriptor.
|
|
|
|
return GetStretchForDescriptor(aVal.GetPairValue().mXValue);
|
2018-04-23 17:52:20 +03:00
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown font-style descriptor value");
|
|
|
|
return FontStretch::Normal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-21 22:07:31 +03:00
|
|
|
/* static */ already_AddRefed<gfxUserFontEntry>
|
2014-10-02 06:32:08 +04:00
|
|
|
FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
|
|
|
|
FontFace* aFontFace,
|
2015-10-20 02:16:20 +03:00
|
|
|
SheetType aSheetType)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2017-12-21 22:07:31 +03:00
|
|
|
FontFaceSet* set = aFontFace->GetPrimaryFontFaceSet();
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
nsCSSValue val;
|
2015-03-27 13:13:21 +03:00
|
|
|
nsCSSUnit unit;
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
uint32_t languageOverride = NO_FONT_LANGUAGE_OVERRIDE;
|
2016-01-07 08:03:05 +03:00
|
|
|
uint8_t fontDisplay = NS_FONT_DISPLAY_AUTO;
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
// set up weight
|
2014-10-02 06:32:08 +04:00
|
|
|
aFontFace->GetDesc(eCSSFontDesc_Weight, val);
|
2018-04-25 12:18:07 +03:00
|
|
|
FontWeight weight = GetWeightForDescriptor(val);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
// set up stretch
|
2014-10-02 06:32:08 +04:00
|
|
|
aFontFace->GetDesc(eCSSFontDesc_Stretch, val);
|
2018-04-25 12:18:07 +03:00
|
|
|
FontStretch stretch = GetStretchForDescriptor(val);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
// set up font style
|
2014-10-02 06:32:08 +04:00
|
|
|
aFontFace->GetDesc(eCSSFontDesc_Style, val);
|
2018-04-25 12:18:07 +03:00
|
|
|
FontSlantStyle italicStyle = GetStyleForDescriptor(val);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2016-01-07 08:03:05 +03:00
|
|
|
// set up font display
|
|
|
|
aFontFace->GetDesc(eCSSFontDesc_Display, val);
|
|
|
|
unit = val.GetUnit();
|
|
|
|
if (unit == eCSSUnit_Enumerated) {
|
|
|
|
fontDisplay = val.GetIntValue();
|
|
|
|
} else {
|
|
|
|
NS_ASSERTION(unit == eCSSUnit_Null,
|
|
|
|
"@font-face style has unexpected unit");
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
// set up font features
|
|
|
|
nsTArray<gfxFontFeature> featureSettings;
|
2014-10-02 06:32:08 +04:00
|
|
|
aFontFace->GetDesc(eCSSFontDesc_FontFeatureSettings, val);
|
2014-10-02 06:32:05 +04:00
|
|
|
unit = val.GetUnit();
|
|
|
|
if (unit == eCSSUnit_Normal) {
|
|
|
|
// empty list of features
|
|
|
|
} else if (unit == eCSSUnit_PairList || unit == eCSSUnit_PairListDep) {
|
2017-11-20 07:43:21 +03:00
|
|
|
nsLayoutUtils::ComputeFontFeatures(val.GetPairListValue(), featureSettings);
|
2014-10-02 06:32:05 +04:00
|
|
|
} else {
|
|
|
|
NS_ASSERTION(unit == eCSSUnit_Null,
|
|
|
|
"@font-face font-feature-settings has unexpected unit");
|
|
|
|
}
|
|
|
|
|
2018-02-14 14:02:05 +03:00
|
|
|
// set up font variations
|
|
|
|
nsTArray<gfxFontVariation> variationSettings;
|
|
|
|
aFontFace->GetDesc(eCSSFontDesc_FontVariationSettings, val);
|
|
|
|
unit = val.GetUnit();
|
|
|
|
if (unit == eCSSUnit_Normal) {
|
|
|
|
// empty list of variations
|
|
|
|
} else if (unit == eCSSUnit_PairList || unit == eCSSUnit_PairListDep) {
|
|
|
|
nsLayoutUtils::ComputeFontVariations(val.GetPairListValue(), variationSettings);
|
|
|
|
} else {
|
|
|
|
NS_ASSERTION(unit == eCSSUnit_Null,
|
|
|
|
"@font-face font-variation-settings has unexpected unit");
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
// set up font language override
|
2014-10-02 06:32:08 +04:00
|
|
|
aFontFace->GetDesc(eCSSFontDesc_FontLanguageOverride, val);
|
2014-10-02 06:32:05 +04:00
|
|
|
unit = val.GetUnit();
|
|
|
|
if (unit == eCSSUnit_Normal) {
|
|
|
|
// empty feature string
|
|
|
|
} else if (unit == eCSSUnit_String) {
|
|
|
|
nsString stringValue;
|
|
|
|
val.GetStringValue(stringValue);
|
2017-11-20 07:43:21 +03:00
|
|
|
languageOverride = nsLayoutUtils::ParseFontLanguageOverride(stringValue);
|
2014-10-02 06:32:05 +04:00
|
|
|
} else {
|
|
|
|
NS_ASSERTION(unit == eCSSUnit_Null,
|
|
|
|
"@font-face font-language-override has unexpected unit");
|
|
|
|
}
|
|
|
|
|
2014-11-06 07:42:50 +03:00
|
|
|
// set up unicode-range
|
2017-04-20 10:00:59 +03:00
|
|
|
gfxCharacterMap* unicodeRanges = aFontFace->GetUnicodeRangeAsCharacterMap();
|
2014-11-06 07:42:50 +03:00
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
// set up src array
|
|
|
|
nsTArray<gfxFontFaceSrc> srcArray;
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
if (aFontFace->HasFontData()) {
|
|
|
|
gfxFontFaceSrc* face = srcArray.AppendElement();
|
|
|
|
if (!face)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
face->mSourceType = gfxFontFaceSrc::eSourceType_Buffer;
|
|
|
|
face->mBuffer = aFontFace->CreateBufferSource();
|
2017-10-01 04:52:00 +03:00
|
|
|
face->mReferrerPolicy = mozilla::net::RP_Unset;
|
2014-10-02 06:32:09 +04:00
|
|
|
} else {
|
|
|
|
aFontFace->GetDesc(eCSSFontDesc_Src, val);
|
|
|
|
unit = val.GetUnit();
|
|
|
|
if (unit == eCSSUnit_Array) {
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
// Hold a strong reference because content of val is going away
|
|
|
|
// in the loop below.
|
|
|
|
RefPtr<nsCSSValue::Array> srcArr = val.GetArrayValue();
|
2014-10-02 06:32:09 +04:00
|
|
|
size_t numSrc = srcArr->Count();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < numSrc; i++) {
|
|
|
|
val = srcArr->Item(i);
|
|
|
|
unit = val.GetUnit();
|
|
|
|
gfxFontFaceSrc* face = srcArray.AppendElements(1);
|
|
|
|
if (!face)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
switch (unit) {
|
|
|
|
|
|
|
|
case eCSSUnit_Local_Font:
|
|
|
|
val.GetStringValue(face->mLocalName);
|
|
|
|
face->mSourceType = gfxFontFaceSrc::eSourceType_Local;
|
|
|
|
face->mURI = nullptr;
|
|
|
|
face->mFormatFlags = 0;
|
2017-10-01 04:52:00 +03:00
|
|
|
face->mReferrerPolicy = mozilla::net::RP_Unset;
|
2014-10-02 06:32:09 +04:00
|
|
|
break;
|
2017-03-30 10:54:48 +03:00
|
|
|
case eCSSUnit_URL: {
|
2014-10-02 06:32:09 +04:00
|
|
|
face->mSourceType = gfxFontFaceSrc::eSourceType_URL;
|
2017-07-08 09:10:05 +03:00
|
|
|
nsIURI* uri = val.GetURLValue();
|
|
|
|
face->mURI = uri ? new gfxFontSrcURI(uri) : nullptr;
|
2017-03-30 10:54:48 +03:00
|
|
|
URLValue* url = val.GetURLStructValue();
|
|
|
|
face->mReferrer = url->mExtraData->GetReferrer();
|
2017-12-21 22:07:31 +03:00
|
|
|
face->mReferrerPolicy = set->mDocument->GetReferrerPolicy();
|
2017-07-08 13:00:24 +03:00
|
|
|
face->mOriginPrincipal =
|
|
|
|
new gfxFontSrcPrincipal(url->mExtraData->GetPrincipal());
|
2014-10-02 06:32:09 +04:00
|
|
|
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
|
|
|
|
|
|
|
|
// agent and user stylesheets are treated slightly differently,
|
|
|
|
// the same-site origin check and access control headers are
|
|
|
|
// enforced against the sheet principal rather than the document
|
|
|
|
// principal to allow user stylesheets to include @font-face rules
|
2015-10-20 02:16:20 +03:00
|
|
|
face->mUseOriginPrincipal = (aSheetType == SheetType::User ||
|
|
|
|
aSheetType == SheetType::Agent);
|
2014-10-02 06:32:09 +04:00
|
|
|
|
|
|
|
face->mLocalName.Truncate();
|
|
|
|
face->mFormatFlags = 0;
|
2017-04-10 07:11:45 +03:00
|
|
|
|
|
|
|
while (i + 1 < numSrc) {
|
|
|
|
val = srcArr->Item(i + 1);
|
|
|
|
if (val.GetUnit() != eCSSUnit_Font_Format)
|
|
|
|
break;
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
nsDependentString valueString(val.GetStringBufferValue());
|
|
|
|
if (valueString.LowerCaseEqualsASCII("woff")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF;
|
2014-10-04 14:36:05 +04:00
|
|
|
} else if (Preferences::GetBool(GFX_PREF_WOFF2_ENABLED) &&
|
|
|
|
valueString.LowerCaseEqualsASCII("woff2")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF2;
|
2014-10-02 06:32:09 +04:00
|
|
|
} else if (valueString.LowerCaseEqualsASCII("opentype")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE;
|
|
|
|
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE;
|
|
|
|
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT;
|
|
|
|
} else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;
|
|
|
|
} else if (valueString.LowerCaseEqualsASCII("svg")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;
|
2018-03-20 02:56:37 +03:00
|
|
|
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
2018-02-15 13:56:42 +03:00
|
|
|
valueString.LowerCaseEqualsASCII("woff-variations")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF_VARIATIONS;
|
2018-03-20 02:56:37 +03:00
|
|
|
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
2018-02-15 13:56:42 +03:00
|
|
|
Preferences::GetBool(GFX_PREF_WOFF2_ENABLED) &&
|
|
|
|
valueString.LowerCaseEqualsASCII("woff2-variations")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF2_VARIATIONS;
|
2018-03-20 02:56:37 +03:00
|
|
|
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
2018-02-15 13:56:42 +03:00
|
|
|
valueString.LowerCaseEqualsASCII("opentype-variations")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE_VARIATIONS;
|
2018-03-20 02:56:37 +03:00
|
|
|
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
2018-02-15 13:56:42 +03:00
|
|
|
valueString.LowerCaseEqualsASCII("truetype-variations")) {
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_VARIATIONS;
|
2014-10-02 06:32:09 +04:00
|
|
|
} else {
|
|
|
|
// unknown format specified, mark to distinguish from the
|
|
|
|
// case where no format hints are specified
|
|
|
|
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_UNKNOWN;
|
|
|
|
}
|
|
|
|
i++;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
if (!face->mURI) {
|
|
|
|
// if URI not valid, omit from src array
|
2018-03-13 16:51:33 +03:00
|
|
|
srcArray.RemoveLastElement();
|
2014-10-02 06:32:09 +04:00
|
|
|
NS_WARNING("null url in @font-face rule");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2017-03-30 10:54:48 +03:00
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
default:
|
|
|
|
NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
|
|
|
|
"strange unit type in font-face src array");
|
|
|
|
break;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
NS_ASSERTION(unit == eCSSUnit_Null, "@font-face src has unexpected unit");
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (srcArray.IsEmpty()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxUserFontEntry> entry =
|
2017-12-21 22:07:31 +03:00
|
|
|
set->mUserFontSet->FindOrCreateUserFontEntry(aFamilyName, srcArray, weight,
|
|
|
|
stretch, italicStyle,
|
|
|
|
featureSettings,
|
2018-02-14 14:02:05 +03:00
|
|
|
variationSettings,
|
2017-12-21 22:07:31 +03:00
|
|
|
languageOverride,
|
|
|
|
unicodeRanges, fontDisplay);
|
2014-10-02 06:32:05 +04:00
|
|
|
return entry.forget();
|
|
|
|
}
|
|
|
|
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
RawServoFontFaceRule*
|
2014-10-02 06:32:05 +04:00
|
|
|
FontFaceSet::FindRuleForEntry(gfxFontEntry* aFontEntry)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aFontEntry->mIsUserFontContainer, "only platform font entries");
|
2014-10-02 06:32:10 +04:00
|
|
|
for (uint32_t i = 0; i < mRuleFaces.Length(); ++i) {
|
|
|
|
FontFace* f = mRuleFaces[i].mFontFace;
|
2014-10-02 06:32:08 +04:00
|
|
|
gfxUserFontEntry* entry = f->GetUserFontEntry();
|
|
|
|
if (entry && entry->GetPlatformFontEntry() == aFontEntry) {
|
|
|
|
return f->GetRule();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
RawServoFontFaceRule*
|
2014-10-02 06:32:05 +04:00
|
|
|
FontFaceSet::FindRuleForUserFontEntry(gfxUserFontEntry* aUserFontEntry)
|
|
|
|
{
|
2014-10-02 06:32:10 +04:00
|
|
|
for (uint32_t i = 0; i < mRuleFaces.Length(); ++i) {
|
|
|
|
FontFace* f = mRuleFaces[i].mFontFace;
|
2014-10-02 06:32:08 +04:00
|
|
|
if (f->GetUserFontEntry() == aUserFontEntry) {
|
|
|
|
return f->GetRule();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
FontFaceSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
|
|
|
|
const char* aMessage,
|
|
|
|
uint32_t aFlags,
|
|
|
|
nsresult aStatus)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIConsoleService>
|
|
|
|
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
|
|
|
if (!console) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString familyName;
|
|
|
|
nsAutoCString fontURI;
|
|
|
|
aUserFontEntry->GetFamilyNameAndURIForLogging(familyName, fontURI);
|
|
|
|
|
2018-04-25 09:18:23 +03:00
|
|
|
nsAutoCString weightString;
|
|
|
|
aUserFontEntry->Weight().ToString(weightString);
|
2014-10-02 06:32:05 +04:00
|
|
|
nsPrintfCString message
|
|
|
|
("downloadable font: %s "
|
2018-04-25 09:18:23 +03:00
|
|
|
"(font-family: \"%s\" style:%s weight:%s stretch:%g%% src index:%d)",
|
2014-10-02 06:32:05 +04:00
|
|
|
aMessage,
|
|
|
|
familyName.get(),
|
2018-04-25 12:18:07 +03:00
|
|
|
aUserFontEntry->IsItalic() ? "italic" : "normal",
|
2018-04-25 09:18:23 +03:00
|
|
|
weightString.get(),
|
2018-04-25 12:18:07 +03:00
|
|
|
aUserFontEntry->Stretch().Percentage(),
|
2014-10-02 06:32:05 +04:00
|
|
|
aUserFontEntry->GetSrcIndex());
|
|
|
|
|
|
|
|
if (NS_FAILED(aStatus)) {
|
|
|
|
message.AppendLiteral(": ");
|
|
|
|
switch (aStatus) {
|
|
|
|
case NS_ERROR_DOM_BAD_URI:
|
|
|
|
message.AppendLiteral("bad URI or cross-site access not allowed");
|
|
|
|
break;
|
|
|
|
case NS_ERROR_CONTENT_BLOCKED:
|
|
|
|
message.AppendLiteral("content blocked");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
message.AppendLiteral("status=");
|
|
|
|
message.AppendInt(static_cast<uint32_t>(aStatus));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-10-17 04:15:29 +04:00
|
|
|
message.AppendLiteral(" source: ");
|
2014-10-02 06:32:05 +04:00
|
|
|
message.Append(fontURI);
|
|
|
|
|
2015-01-29 10:44:59 +03:00
|
|
|
if (LOG_ENABLED()) {
|
|
|
|
LOG(("userfonts (%p) %s", mUserFontSet.get(), message.get()));
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// try to give the user an indication of where the rule came from
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
RawServoFontFaceRule* rule = FindRuleForUserFontEntry(aUserFontEntry);
|
2014-10-02 06:32:05 +04:00
|
|
|
nsString href;
|
|
|
|
nsString text;
|
2014-10-02 10:06:39 +04:00
|
|
|
uint32_t line = 0;
|
|
|
|
uint32_t column = 0;
|
2014-10-02 06:32:05 +04:00
|
|
|
if (rule) {
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
Servo_FontFaceRule_GetCssText(rule, &text);
|
|
|
|
Servo_FontFaceRule_GetSourceLocation(rule, &line, &column);
|
|
|
|
// FIXME We need to figure out an approach to get the style sheet
|
|
|
|
// of this raw rule. See bug 1450903.
|
|
|
|
#if 0
|
2016-11-23 02:26:20 +03:00
|
|
|
StyleSheet* sheet = rule->GetStyleSheet();
|
2014-10-02 06:32:05 +04:00
|
|
|
// if the style sheet is removed while the font is loading can be null
|
|
|
|
if (sheet) {
|
2016-08-31 13:10:10 +03:00
|
|
|
nsCString spec = sheet->GetSheetURI()->GetSpecOrDefault();
|
2014-10-02 08:23:53 +04:00
|
|
|
CopyUTF8toUTF16(spec, href);
|
2014-10-02 06:32:05 +04:00
|
|
|
} else {
|
|
|
|
NS_WARNING("null parent stylesheet for @font-face rule");
|
|
|
|
href.AssignLiteral("unknown");
|
|
|
|
}
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
#endif
|
|
|
|
href.AssignLiteral("unknown");
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2018-01-11 11:17:56 +03:00
|
|
|
nsresult rv;
|
2014-10-02 06:32:05 +04:00
|
|
|
nsCOMPtr<nsIScriptError> scriptError =
|
|
|
|
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2015-06-27 04:39:54 +03:00
|
|
|
uint64_t innerWindowID = mDocument->InnerWindowID();
|
2014-10-02 06:32:05 +04:00
|
|
|
rv = scriptError->InitWithWindowID(NS_ConvertUTF8toUTF16(message),
|
|
|
|
href, // file
|
|
|
|
text, // src line
|
2014-10-02 10:06:39 +04:00
|
|
|
line,
|
|
|
|
column,
|
2014-10-02 06:32:05 +04:00
|
|
|
aFlags, // flags
|
|
|
|
"CSS Loader", // category (make separate?)
|
|
|
|
innerWindowID);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
console->LogMessage(scriptError);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::CacheFontLoadability()
|
2017-07-07 08:35:28 +03:00
|
|
|
{
|
2018-03-23 18:06:56 +03:00
|
|
|
if (!mUserFontSet) {
|
|
|
|
return;
|
2017-07-08 13:00:24 +03:00
|
|
|
}
|
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
// TODO(emilio): We could do it a bit more incrementally maybe?
|
|
|
|
for (auto iter = mUserFontSet->mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
for (const gfxFontEntry* entry : iter.Data()->GetFontList()) {
|
|
|
|
if (!entry->mIsUserFontContainer) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto& sourceList =
|
|
|
|
static_cast<const gfxUserFontEntry*>(entry)->SourceList();
|
|
|
|
for (const gfxFontFaceSrc& src : sourceList) {
|
|
|
|
if (src.mSourceType != gfxFontFaceSrc::eSourceType_URL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
mAllowedFontLoads.LookupForAdd(&src).OrInsert([&] {
|
|
|
|
return IsFontLoadAllowed(src);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-07-07 08:35:28 +03:00
|
|
|
}
|
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
bool
|
|
|
|
FontFaceSet::IsFontLoadAllowed(const gfxFontFaceSrc& aSrc)
|
2014-10-02 06:32:05 +04:00
|
|
|
{
|
2018-03-23 18:06:56 +03:00
|
|
|
MOZ_ASSERT(aSrc.mSourceType == gfxFontFaceSrc::eSourceType_URL);
|
2015-06-27 04:39:54 +03:00
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
if (ServoStyleSet::IsInServoTraversal()) {
|
|
|
|
bool* entry = mAllowedFontLoads.GetValue(&aSrc);
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(entry, "Missed an update?");
|
|
|
|
return entry ? *entry : false;
|
|
|
|
}
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
if (!mUserFontSet) {
|
|
|
|
return false;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
gfxFontSrcPrincipal* gfxPrincipal =
|
|
|
|
aSrc.mURI->InheritsSecurityContext()
|
|
|
|
? nullptr : aSrc.LoadPrincipal(*mUserFontSet);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
2018-03-23 18:06:56 +03:00
|
|
|
nsIPrincipal* principal = gfxPrincipal ? gfxPrincipal->get() : nullptr;
|
2017-08-07 05:12:12 +03:00
|
|
|
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
|
|
|
|
new net::LoadInfo(mDocument->NodePrincipal(), // loading principal
|
2018-03-23 18:06:56 +03:00
|
|
|
principal, // triggering principal
|
2018-03-29 13:16:23 +03:00
|
|
|
mDocument,
|
|
|
|
nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
|
|
|
|
nsIContentPolicy::TYPE_FONT);
|
|
|
|
|
2016-03-02 00:06:13 +03:00
|
|
|
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
2018-03-23 18:06:56 +03:00
|
|
|
nsresult rv = NS_CheckContentLoadPolicy(aSrc.mURI->get(),
|
2018-03-29 13:16:23 +03:00
|
|
|
secCheckLoadInfo,
|
2016-03-02 00:06:13 +03:00
|
|
|
EmptyCString(), // mime type
|
|
|
|
&shouldLoad,
|
2017-07-11 01:00:03 +03:00
|
|
|
nsContentUtils::GetContentPolicy());
|
2016-03-02 00:06:13 +03:00
|
|
|
|
|
|
|
return NS_SUCCEEDED(rv) && NS_CP_ACCEPTED(shouldLoad);
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
2017-08-07 05:12:12 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::DispatchFontLoadViolations(
|
|
|
|
nsTArray<nsCOMPtr<nsIRunnable>>& aViolations)
|
|
|
|
{
|
|
|
|
if (XRE_IsContentProcess()) {
|
|
|
|
nsCOMPtr<nsIEventTarget> eventTarget =
|
|
|
|
mDocument->EventTargetFor(TaskCategory::Other);
|
|
|
|
for (nsIRunnable* runnable : aViolations) {
|
|
|
|
eventTarget->Dispatch(do_AddRef(runnable), NS_DISPATCH_NORMAL);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (nsIRunnable* runnable : aViolations) {
|
|
|
|
NS_DispatchToMainThread(do_AddRef(runnable));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
nsresult
|
|
|
|
FontFaceSet::SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
|
|
|
|
const gfxFontFaceSrc* aFontFaceSrc,
|
|
|
|
uint8_t*& aBuffer,
|
|
|
|
uint32_t& aBufferLength)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2017-07-08 13:00:24 +03:00
|
|
|
gfxFontSrcPrincipal* principal = aFontToLoad->GetPrincipal();
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2014-11-14 19:56:55 +03:00
|
|
|
// Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
|
|
|
|
// node and a principal. This is because the document where the font is
|
|
|
|
// being loaded might have a different origin from the principal of the
|
|
|
|
// stylesheet that initiated the font load.
|
2016-03-02 00:06:13 +03:00
|
|
|
// Further, we only get here for data: loads, so it doesn't really matter
|
|
|
|
// whether we use SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS or not, to be more
|
|
|
|
// restrictive we use SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS.
|
2014-11-14 19:56:55 +03:00
|
|
|
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
|
2017-07-08 09:10:05 +03:00
|
|
|
aFontFaceSrc->mURI->get(),
|
2015-06-27 04:39:54 +03:00
|
|
|
mDocument,
|
2017-07-08 13:00:24 +03:00
|
|
|
principal ? principal->get() : nullptr,
|
2016-03-02 00:06:13 +03:00
|
|
|
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
|
2014-11-14 19:56:55 +03:00
|
|
|
nsIContentPolicy::TYPE_FONT);
|
2014-10-02 06:32:05 +04:00
|
|
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// blocking stream is OK for data URIs
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
2016-03-02 00:06:13 +03:00
|
|
|
rv = channel->Open2(getter_AddRefs(stream));
|
2014-10-02 06:32:05 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
uint64_t bufferLength64;
|
|
|
|
rv = stream->Available(&bufferLength64);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (bufferLength64 == 0) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
if (bufferLength64 > UINT32_MAX) {
|
|
|
|
return NS_ERROR_FILE_TOO_BIG;
|
|
|
|
}
|
|
|
|
aBufferLength = static_cast<uint32_t>(bufferLength64);
|
|
|
|
|
|
|
|
// read all the decoded data
|
2017-08-08 20:22:10 +03:00
|
|
|
aBuffer = static_cast<uint8_t*>(malloc(sizeof(uint8_t) * aBufferLength));
|
2014-10-02 06:32:05 +04:00
|
|
|
if (!aBuffer) {
|
|
|
|
aBufferLength = 0;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t numRead, totalRead = 0;
|
|
|
|
while (NS_SUCCEEDED(rv =
|
|
|
|
stream->Read(reinterpret_cast<char*>(aBuffer + totalRead),
|
|
|
|
aBufferLength - totalRead, &numRead)) &&
|
|
|
|
numRead != 0)
|
|
|
|
{
|
|
|
|
totalRead += numRead;
|
|
|
|
if (totalRead > aBufferLength) {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure there's a mime type
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsAutoCString mimeType;
|
|
|
|
rv = channel->GetContentType(mimeType);
|
|
|
|
aBufferLength = totalRead;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
2015-04-01 08:29:55 +03:00
|
|
|
free(aBuffer);
|
2014-10-02 06:32:05 +04:00
|
|
|
aBuffer = nullptr;
|
|
|
|
aBufferLength = 0;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
void
|
|
|
|
FontFaceSet::OnFontFaceStatusChanged(FontFace* aFontFace)
|
|
|
|
{
|
2017-04-30 09:55:22 +03:00
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
MOZ_ASSERT(HasAvailableFontFace(aFontFace));
|
|
|
|
|
|
|
|
mHasLoadingFontFacesIsDirty = true;
|
|
|
|
|
|
|
|
if (aFontFace->Status() == FontFaceLoadStatus::Loading) {
|
|
|
|
CheckLoadingStarted();
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(aFontFace->Status() == FontFaceLoadStatus::Loaded ||
|
|
|
|
aFontFace->Status() == FontFaceLoadStatus::Error);
|
2015-03-27 13:05:22 +03:00
|
|
|
// When a font finishes downloading, nsPresContext::UserFontSetUpdated
|
|
|
|
// will be called immediately afterwards to request a reflow of the
|
|
|
|
// relevant elements in the document. We want to wait until the reflow
|
|
|
|
// request has been done before the FontFaceSet is marked as Loaded so
|
|
|
|
// that we don't briefly set the FontFaceSet to Loaded and then Loading
|
|
|
|
// again once the reflow is pending. So we go around the event loop
|
|
|
|
// and call CheckLoadingFinished() after the reflow has been queued.
|
|
|
|
if (!mDelayedLoadCheck) {
|
|
|
|
mDelayedLoadCheck = true;
|
2017-04-30 09:55:22 +03:00
|
|
|
DispatchCheckLoadingFinishedAfterDelay();
|
2015-03-27 13:05:22 +03:00
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-30 09:55:22 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::DispatchCheckLoadingFinishedAfterDelay()
|
|
|
|
{
|
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
|
|
|
if (ServoStyleSet* set = ServoStyleSet::Current()) {
|
|
|
|
// See comments in Gecko_GetFontMetrics.
|
|
|
|
//
|
|
|
|
// We can't just dispatch the runnable below if we're not on the main
|
|
|
|
// thread, since it needs to take a strong reference to the FontFaceSet,
|
|
|
|
// and being a DOM object, FontFaceSet doesn't support thread-safe
|
|
|
|
// refcounting.
|
|
|
|
set->AppendTask(PostTraversalTask::DispatchFontFaceSetCheckLoadingFinishedAfterDelay(this));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> checkTask =
|
2017-06-12 22:34:10 +03:00
|
|
|
NewRunnableMethod("dom::FontFaceSet::CheckLoadingFinishedAfterDelay",
|
|
|
|
this,
|
|
|
|
&FontFaceSet::CheckLoadingFinishedAfterDelay);
|
2017-07-26 11:13:35 +03:00
|
|
|
mDocument->Dispatch(TaskCategory::Other, checkTask.forget());
|
2017-04-30 09:55:22 +03:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
void
|
|
|
|
FontFaceSet::DidRefresh()
|
|
|
|
{
|
|
|
|
CheckLoadingFinished();
|
|
|
|
}
|
|
|
|
|
2015-03-27 13:05:22 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::CheckLoadingFinishedAfterDelay()
|
|
|
|
{
|
|
|
|
mDelayedLoadCheck = false;
|
|
|
|
CheckLoadingFinished();
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
void
|
|
|
|
FontFaceSet::CheckLoadingStarted()
|
|
|
|
{
|
2017-04-30 09:55:22 +03:00
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
2015-03-24 11:34:32 +03:00
|
|
|
if (!HasLoadingFontFaces()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-24 11:34:32 +03:00
|
|
|
if (mStatus == FontFaceSetLoadStatus::Loading) {
|
|
|
|
// We have already dispatched a loading event and replaced mReady
|
|
|
|
// with a fresh, unresolved promise.
|
|
|
|
return;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2015-03-24 11:34:32 +03:00
|
|
|
mStatus = FontFaceSetLoadStatus::Loading;
|
2017-04-30 09:55:22 +03:00
|
|
|
DispatchLoadingEventAndReplaceReadyPromise();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::DispatchLoadingEventAndReplaceReadyPromise()
|
|
|
|
{
|
|
|
|
AssertIsMainThreadOrServoFontMetricsLocked();
|
|
|
|
|
|
|
|
if (ServoStyleSet* set = ServoStyleSet::Current()) {
|
|
|
|
// See comments in Gecko_GetFontMetrics.
|
|
|
|
//
|
|
|
|
// We can't just dispatch the runnable below if we're not on the main
|
|
|
|
// thread, since it needs to take a strong reference to the FontFaceSet,
|
|
|
|
// and being a DOM object, FontFaceSet doesn't support thread-safe
|
|
|
|
// refcounting. (Also, the Promise object creation must be done on
|
|
|
|
// the main thread.)
|
|
|
|
set->AppendTask(
|
|
|
|
PostTraversalTask::DispatchLoadingEventAndReplaceReadyPromise(this));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-24 11:34:32 +03:00
|
|
|
(new AsyncEventDispatcher(this, NS_LITERAL_STRING("loading"),
|
2017-02-07 13:49:28 +03:00
|
|
|
false))->PostDOMEvent();
|
2015-03-24 11:34:32 +03:00
|
|
|
|
2015-03-24 11:34:32 +03:00
|
|
|
if (PrefEnabled()) {
|
2016-10-13 22:08:53 +03:00
|
|
|
if (mReady) {
|
|
|
|
if (GetParentObject()) {
|
|
|
|
ErrorResult rv;
|
|
|
|
mReady = Promise::Create(GetParentObject(), rv);
|
|
|
|
}
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
2016-10-13 22:08:53 +03:00
|
|
|
if (!mReady) {
|
|
|
|
mResolveLazilyCreatedReadyPromise = false;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::UpdateHasLoadingFontFaces()
|
|
|
|
{
|
|
|
|
mHasLoadingFontFacesIsDirty = false;
|
|
|
|
mHasLoadingFontFaces = false;
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < mRuleFaces.Length(); i++) {
|
|
|
|
FontFace* f = mRuleFaces[i].mFontFace;
|
2014-10-02 06:32:09 +04:00
|
|
|
if (f->Status() == FontFaceLoadStatus::Loading) {
|
|
|
|
mHasLoadingFontFaces = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < mNonRuleFaces.Length(); i++) {
|
2015-03-27 13:05:22 +03:00
|
|
|
if (mNonRuleFaces[i].mFontFace->Status() == FontFaceLoadStatus::Loading) {
|
2014-10-02 06:32:09 +04:00
|
|
|
mHasLoadingFontFaces = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
FontFaceSet::HasLoadingFontFaces()
|
|
|
|
{
|
|
|
|
if (mHasLoadingFontFacesIsDirty) {
|
|
|
|
UpdateHasLoadingFontFaces();
|
|
|
|
}
|
|
|
|
return mHasLoadingFontFaces;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
FontFaceSet::MightHavePendingFontLoads()
|
|
|
|
{
|
|
|
|
// Check for FontFace objects in the FontFaceSet that are still loading.
|
|
|
|
if (HasLoadingFontFaces()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for pending restyles or reflows, as they might cause fonts to
|
|
|
|
// load as new styles apply and text runs are rebuilt.
|
2015-06-27 04:39:54 +03:00
|
|
|
nsPresContext* presContext = GetPresContext();
|
|
|
|
if (presContext && presContext->HasPendingRestyleOrReflow()) {
|
2014-10-02 06:32:09 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDocument) {
|
|
|
|
// We defer resolving mReady until the document as fully loaded.
|
|
|
|
if (!mDocument->DidFireDOMContentLoaded()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// And we also wait for any CSS style sheets to finish loading, as their
|
|
|
|
// styles might cause new fonts to load.
|
|
|
|
if (mDocument->CSSLoader()->HasPendingLoads()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::CheckLoadingFinished()
|
|
|
|
{
|
2017-04-30 09:55:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2015-03-27 13:05:22 +03:00
|
|
|
if (mDelayedLoadCheck) {
|
|
|
|
// Wait until the runnable posted in OnFontFaceStatusChanged calls us.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-24 11:34:32 +03:00
|
|
|
if (mStatus == FontFaceSetLoadStatus::Loaded) {
|
2014-10-02 06:32:09 +04:00
|
|
|
// We've already resolved mReady and dispatched the loadingdone/loadingerror
|
|
|
|
// events.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MightHavePendingFontLoads()) {
|
|
|
|
// We're not finished loading yet.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mStatus = FontFaceSetLoadStatus::Loaded;
|
|
|
|
if (mReady) {
|
|
|
|
mReady->MaybeResolve(this);
|
2016-10-13 22:08:53 +03:00
|
|
|
} else {
|
|
|
|
mResolveLazilyCreatedReadyPromise = true;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now dispatch the loadingdone/loadingerror events.
|
2017-02-07 17:53:00 +03:00
|
|
|
nsTArray<OwningNonNull<FontFace>> loaded;
|
|
|
|
nsTArray<OwningNonNull<FontFace>> failed;
|
2014-10-02 06:32:09 +04:00
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < mRuleFaces.Length(); i++) {
|
2015-03-27 13:05:22 +03:00
|
|
|
if (!mRuleFaces[i].mLoadEventShouldFire) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-10-02 06:32:10 +04:00
|
|
|
FontFace* f = mRuleFaces[i].mFontFace;
|
2014-10-02 06:32:09 +04:00
|
|
|
if (f->Status() == FontFaceLoadStatus::Loaded) {
|
2017-02-07 17:53:00 +03:00
|
|
|
loaded.AppendElement(*f);
|
2015-03-27 13:05:22 +03:00
|
|
|
mRuleFaces[i].mLoadEventShouldFire = false;
|
2014-10-02 06:32:09 +04:00
|
|
|
} else if (f->Status() == FontFaceLoadStatus::Error) {
|
2017-02-07 17:53:00 +03:00
|
|
|
failed.AppendElement(*f);
|
2015-03-27 13:05:22 +03:00
|
|
|
mRuleFaces[i].mLoadEventShouldFire = false;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:10 +04:00
|
|
|
for (size_t i = 0; i < mNonRuleFaces.Length(); i++) {
|
2015-03-27 13:05:22 +03:00
|
|
|
if (!mNonRuleFaces[i].mLoadEventShouldFire) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
FontFace* f = mNonRuleFaces[i].mFontFace;
|
2014-10-02 06:32:09 +04:00
|
|
|
if (f->Status() == FontFaceLoadStatus::Loaded) {
|
2017-02-07 17:53:00 +03:00
|
|
|
loaded.AppendElement(*f);
|
2015-03-27 13:05:22 +03:00
|
|
|
mNonRuleFaces[i].mLoadEventShouldFire = false;
|
2014-10-02 06:32:09 +04:00
|
|
|
} else if (f->Status() == FontFaceLoadStatus::Error) {
|
2017-02-07 17:53:00 +03:00
|
|
|
failed.AppendElement(*f);
|
2015-03-27 13:05:22 +03:00
|
|
|
mNonRuleFaces[i].mLoadEventShouldFire = false;
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-07 17:53:00 +03:00
|
|
|
DispatchLoadingFinishedEvent(NS_LITERAL_STRING("loadingdone"),
|
|
|
|
Move(loaded));
|
2014-10-02 06:32:09 +04:00
|
|
|
|
|
|
|
if (!failed.IsEmpty()) {
|
2017-02-07 17:53:00 +03:00
|
|
|
DispatchLoadingFinishedEvent(NS_LITERAL_STRING("loadingerror"),
|
|
|
|
Move(failed));
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FontFaceSet::DispatchLoadingFinishedEvent(
|
|
|
|
const nsAString& aType,
|
2017-02-07 17:53:00 +03:00
|
|
|
nsTArray<OwningNonNull<FontFace>>&& aFontFaces)
|
2014-10-02 06:32:09 +04:00
|
|
|
{
|
2015-08-11 05:19:52 +03:00
|
|
|
FontFaceSetLoadEventInit init;
|
2014-10-02 06:32:09 +04:00
|
|
|
init.mBubbles = false;
|
|
|
|
init.mCancelable = false;
|
2017-02-07 17:53:00 +03:00
|
|
|
init.mFontfaces.SwapElements(aFontFaces);
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<FontFaceSetLoadEvent> event =
|
2015-08-11 05:19:52 +03:00
|
|
|
FontFaceSetLoadEvent::Constructor(this, aType, init);
|
2017-02-07 13:49:28 +03:00
|
|
|
(new AsyncEventDispatcher(this, event))->PostDOMEvent();
|
2014-10-02 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// nsIDOMEventListener
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2018-04-20 07:49:29 +03:00
|
|
|
FontFaceSet::HandleEvent(Event* aEvent)
|
2014-10-02 06:32:09 +04:00
|
|
|
{
|
|
|
|
nsString type;
|
|
|
|
aEvent->GetType(type);
|
|
|
|
|
|
|
|
if (!type.EqualsLiteral("DOMContentLoaded")) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2015-05-13 08:06:52 +03:00
|
|
|
RemoveDOMContentLoadedListener();
|
2014-10-02 06:32:09 +04:00
|
|
|
CheckLoadingFinished();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-11-11 06:53:55 +03:00
|
|
|
/* static */ bool
|
|
|
|
FontFaceSet::PrefEnabled()
|
|
|
|
{
|
|
|
|
static bool initialized = false;
|
|
|
|
static bool enabled;
|
|
|
|
if (!initialized) {
|
|
|
|
initialized = true;
|
|
|
|
Preferences::AddBoolVarCache(&enabled, FONT_LOADING_API_ENABLED_PREF);
|
|
|
|
}
|
|
|
|
return enabled;
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:09 +04:00
|
|
|
// nsICSSLoaderObserver
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-09-26 15:03:25 +03:00
|
|
|
FontFaceSet::StyleSheetLoaded(StyleSheet* aSheet,
|
2014-10-02 06:32:09 +04:00
|
|
|
bool aWasAlternate,
|
|
|
|
nsresult aStatus)
|
|
|
|
{
|
|
|
|
CheckLoadingFinished();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-06-27 04:39:54 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::FlushUserFontSet()
|
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
if (mDocument) {
|
|
|
|
mDocument->FlushUserFontSet();
|
2015-06-27 04:39:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-01-31 13:12:36 +03:00
|
|
|
FontFaceSet::MarkUserFontSetDirty()
|
2015-06-27 04:39:54 +03:00
|
|
|
{
|
2015-06-27 04:39:54 +03:00
|
|
|
if (mDocument) {
|
2018-01-31 13:12:36 +03:00
|
|
|
// Ensure we trigger at least a style flush, that will eventually flush the
|
|
|
|
// user font set. Otherwise the font loads that that flush may cause could
|
|
|
|
// never be triggered.
|
|
|
|
if (nsIPresShell* shell = mDocument->GetShell()) {
|
|
|
|
shell->EnsureStyleFlush();
|
|
|
|
}
|
|
|
|
mDocument->MarkUserFontSetDirty();
|
2015-06-27 04:39:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPresContext*
|
|
|
|
FontFaceSet::GetPresContext()
|
|
|
|
{
|
|
|
|
if (!mDocument) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-02-21 01:00:10 +03:00
|
|
|
return mDocument->GetPresContext();
|
2015-06-27 04:39:54 +03:00
|
|
|
}
|
|
|
|
|
2017-07-08 13:00:24 +03:00
|
|
|
void
|
2018-03-23 18:06:56 +03:00
|
|
|
FontFaceSet::RefreshStandardFontLoadPrincipal()
|
2017-07-08 13:00:24 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2018-03-23 18:06:56 +03:00
|
|
|
mStandardFontLoadPrincipal =
|
|
|
|
new gfxFontSrcPrincipal(mDocument->NodePrincipal());
|
|
|
|
mAllowedFontLoads.Clear();
|
|
|
|
if (mUserFontSet) {
|
|
|
|
mUserFontSet->IncrementGeneration(false);
|
2017-07-08 13:00:24 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
// -- FontFaceSet::UserFontSet ------------------------------------------------
|
|
|
|
|
2016-03-02 00:06:13 +03:00
|
|
|
/* virtual */ bool
|
2018-03-23 18:06:56 +03:00
|
|
|
FontFaceSet::UserFontSet::IsFontLoadAllowed(const gfxFontFaceSrc& aSrc)
|
2016-03-02 00:06:13 +03:00
|
|
|
{
|
2018-03-23 18:06:56 +03:00
|
|
|
return mFontFaceSet && mFontFaceSet->IsFontLoadAllowed(aSrc);
|
2017-08-07 05:12:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
FontFaceSet::UserFontSet::DispatchFontLoadViolations(
|
|
|
|
nsTArray<nsCOMPtr<nsIRunnable>>& aViolations)
|
|
|
|
{
|
|
|
|
if (mFontFaceSet) {
|
|
|
|
mFontFaceSet->DispatchFontLoadViolations(aViolations);
|
|
|
|
}
|
2016-03-02 00:06:13 +03:00
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
/* virtual */ nsresult
|
|
|
|
FontFaceSet::UserFontSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
|
|
|
|
const gfxFontFaceSrc* aFontFaceSrc)
|
|
|
|
{
|
|
|
|
if (!mFontFaceSet) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return mFontFaceSet->StartLoad(aUserFontEntry, aFontFaceSrc);
|
|
|
|
}
|
|
|
|
|
2015-11-25 08:48:16 +03:00
|
|
|
void
|
|
|
|
FontFaceSet::UserFontSet::RecordFontLoadDone(uint32_t aFontSize,
|
|
|
|
TimeStamp aDoneTime)
|
|
|
|
{
|
|
|
|
mDownloadCount++;
|
|
|
|
mDownloadSize += aFontSize;
|
|
|
|
Telemetry::Accumulate(Telemetry::WEBFONT_SIZE, aFontSize / 1024);
|
|
|
|
|
|
|
|
if (!mFontFaceSet) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TimeStamp navStart = mFontFaceSet->GetNavigationStartTimeStamp();
|
|
|
|
TimeStamp zero;
|
|
|
|
if (navStart != zero) {
|
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::WEBFONT_DOWNLOAD_TIME_AFTER_START,
|
|
|
|
navStart, aDoneTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-02 06:32:05 +04:00
|
|
|
/* virtual */ nsresult
|
|
|
|
FontFaceSet::UserFontSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
|
|
|
|
const char* aMessage,
|
|
|
|
uint32_t aFlags,
|
|
|
|
nsresult aStatus)
|
|
|
|
{
|
|
|
|
if (!mFontFaceSet) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return mFontFaceSet->LogMessage(aUserFontEntry, aMessage, aFlags, aStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsresult
|
|
|
|
FontFaceSet::UserFontSet::SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
|
|
|
|
const gfxFontFaceSrc* aFontFaceSrc,
|
|
|
|
uint8_t*& aBuffer,
|
|
|
|
uint32_t& aBufferLength)
|
|
|
|
{
|
|
|
|
if (!mFontFaceSet) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return mFontFaceSet->SyncLoadFontData(aFontToLoad, aFontFaceSrc,
|
|
|
|
aBuffer, aBufferLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ bool
|
|
|
|
FontFaceSet::UserFontSet::GetPrivateBrowsing()
|
|
|
|
{
|
2017-07-05 12:41:01 +03:00
|
|
|
return mFontFaceSet && mFontFaceSet->mPrivateBrowsing;
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
FontFaceSet::UserFontSet::DoRebuildUserFontSet()
|
|
|
|
{
|
|
|
|
if (!mFontFaceSet) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-31 13:12:36 +03:00
|
|
|
mFontFaceSet->MarkUserFontSetDirty();
|
2014-10-02 06:32:05 +04:00
|
|
|
}
|
2014-10-02 06:32:06 +04:00
|
|
|
|
|
|
|
/* virtual */ already_AddRefed<gfxUserFontEntry>
|
2014-10-02 06:32:07 +04:00
|
|
|
FontFaceSet::UserFontSet::CreateUserFontEntry(
|
2014-10-02 06:32:06 +04:00
|
|
|
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
2018-04-25 12:18:07 +03:00
|
|
|
FontWeight aWeight,
|
|
|
|
FontStretch aStretch,
|
|
|
|
FontSlantStyle aStyle,
|
2014-10-02 06:32:06 +04:00
|
|
|
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
2018-02-14 14:02:05 +03:00
|
|
|
const nsTArray<gfxFontVariation>& aVariationSettings,
|
2014-10-02 06:32:06 +04:00
|
|
|
uint32_t aLanguageOverride,
|
2017-04-20 10:00:59 +03:00
|
|
|
gfxCharacterMap* aUnicodeRanges,
|
2016-01-07 08:03:05 +03:00
|
|
|
uint8_t aFontDisplay)
|
2014-10-02 06:32:06 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxUserFontEntry> entry =
|
2015-10-19 05:16:43 +03:00
|
|
|
new FontFace::Entry(this, aFontFaceSrcList, aWeight, aStretch, aStyle,
|
2018-02-14 14:02:05 +03:00
|
|
|
aFeatureSettings, aVariationSettings,
|
|
|
|
aLanguageOverride, aUnicodeRanges,
|
2016-01-07 08:03:05 +03:00
|
|
|
aFontDisplay);
|
2014-10-02 06:32:06 +04:00
|
|
|
return entry.forget();
|
|
|
|
}
|
2015-07-02 01:45:00 +03:00
|
|
|
|
|
|
|
#undef LOG_ENABLED
|
|
|
|
#undef LOG
|