2016-02-24 10:01:10 +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: */
|
|
|
|
/* 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 "mozilla/ServoStyleSet.h"
|
|
|
|
|
2017-04-08 01:49:44 +03:00
|
|
|
#include "gfxPlatformFontList.h"
|
2016-12-01 11:19:50 +03:00
|
|
|
#include "mozilla/DocumentStyleRootIterator.h"
|
2016-07-13 23:42:47 +03:00
|
|
|
#include "mozilla/ServoRestyleManager.h"
|
2017-03-18 09:15:09 +03:00
|
|
|
#include "mozilla/dom/AnonymousContent.h"
|
2016-08-12 00:12:49 +03:00
|
|
|
#include "mozilla/dom/ChildIterator.h"
|
2017-01-01 03:10:45 +03:00
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "mozilla/dom/ElementInlines.h"
|
2017-03-11 04:40:47 +03:00
|
|
|
#include "mozilla/dom/KeyframeEffectReadOnly.h"
|
2016-02-24 10:01:10 +03:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
2016-03-18 23:14:07 +03:00
|
|
|
#include "nsCSSPseudoElements.h"
|
2017-04-08 01:49:44 +03:00
|
|
|
#include "nsDeviceContext.h"
|
2017-01-20 02:56:53 +03:00
|
|
|
#include "nsHTMLStyleSheet.h"
|
2016-04-29 07:01:44 +03:00
|
|
|
#include "nsIDocumentInlines.h"
|
2016-07-28 06:03:49 +03:00
|
|
|
#include "nsPrintfCString.h"
|
2016-03-18 23:14:07 +03:00
|
|
|
#include "nsStyleContext.h"
|
2016-02-26 04:51:02 +03:00
|
|
|
#include "nsStyleSet.h"
|
2016-02-24 10:01:10 +03:00
|
|
|
|
|
|
|
using namespace mozilla;
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSet::ServoStyleSet()
|
2016-03-18 23:14:07 +03:00
|
|
|
: mPresContext(nullptr)
|
2016-01-27 05:02:04 +03:00
|
|
|
, mBatching(0)
|
2017-03-28 10:31:41 +03:00
|
|
|
, mAllowResolveStaleStyles(false)
|
2017-04-11 10:43:14 +03:00
|
|
|
, mAuthorStyleDisabled(false)
|
2016-02-24 10:01:12 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-03-08 08:18:39 +03:00
|
|
|
ServoStyleSet::~ServoStyleSet()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:10 +03:00
|
|
|
void
|
|
|
|
ServoStyleSet::Init(nsPresContext* aPresContext)
|
|
|
|
{
|
2016-03-18 23:14:07 +03:00
|
|
|
mPresContext = aPresContext;
|
2017-01-04 22:52:26 +03:00
|
|
|
mRawSet.reset(Servo_StyleSet_Init(aPresContext));
|
|
|
|
|
2017-04-08 01:49:44 +03:00
|
|
|
mPresContext->DeviceContext()->InitFontCache();
|
|
|
|
gfxPlatformFontList::PlatformFontList()->InitLangService();
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
// Now that we have an mRawSet, go ahead and notify about whatever stylesheets
|
|
|
|
// we have so far.
|
|
|
|
for (auto& sheetArray : mSheets) {
|
|
|
|
for (auto& sheet : sheetArray) {
|
|
|
|
// There's no guarantee this will create a list on the servo side whose
|
|
|
|
// ordering matches the list that would have been created had all those
|
|
|
|
// sheets been appended/prepended/etc after we had mRawSet. But hopefully
|
|
|
|
// that's OK (e.g. because servo doesn't care about the relative ordering
|
|
|
|
// of sheets from different cascade levels in the list?).
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(sheet->RawSheet(), "We should only append non-null raw sheets.");
|
2017-01-04 22:52:26 +03:00
|
|
|
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet->RawSheet(), false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No need to Servo_StyleSet_FlushStyleSheets because we just created the
|
|
|
|
// mRawSet, so there was nothing to flush.
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ServoStyleSet::BeginShutdown()
|
|
|
|
{
|
2017-03-18 09:15:09 +03:00
|
|
|
nsIDocument* doc = mPresContext->Document();
|
|
|
|
|
2016-11-18 11:54:10 +03:00
|
|
|
// It's important to do this before mRawSet is released, since that will cause
|
|
|
|
// a RuleTree GC, which needs to happen after we have dropped all of the
|
|
|
|
// document's strong references to RuleNodes. We also need to do it here,
|
|
|
|
// in BeginShutdown, and not in Shutdown, since Shutdown happens after the
|
|
|
|
// frame tree has been destroyed, but before the script runners that delete
|
|
|
|
// native anonymous content (which also could be holding on the RuleNodes)
|
|
|
|
// have run. By clearing style here, before the frame tree is destroyed,
|
|
|
|
// the AllChildrenIterator will find the anonymous content.
|
|
|
|
//
|
|
|
|
// Note that this is pretty bad for performance; we should find a way to
|
|
|
|
// get by with the ServoNodeDatas being dropped as part of the document
|
|
|
|
// going away.
|
2017-03-18 09:15:09 +03:00
|
|
|
DocumentStyleRootIterator iter(doc);
|
2016-12-01 11:19:50 +03:00
|
|
|
while (Element* root = iter.GetNextStyleRoot()) {
|
2016-11-18 11:54:10 +03:00
|
|
|
ServoRestyleManager::ClearServoDataFromSubtree(root);
|
|
|
|
}
|
2017-03-18 09:15:09 +03:00
|
|
|
|
|
|
|
// We can also have some cloned canvas custom content stored in the document
|
|
|
|
// (as done in nsCanvasFrame::DestroyFrom), due to bug 1348480, when we create
|
|
|
|
// the clone (wastefully) during PresShell destruction. Clear data from that
|
|
|
|
// clone.
|
|
|
|
for (RefPtr<AnonymousContent>& ac : doc->GetAnonymousContents()) {
|
|
|
|
ServoRestyleManager::ClearServoDataFromSubtree(ac->GetContentNode());
|
|
|
|
}
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ServoStyleSet::Shutdown()
|
|
|
|
{
|
2017-03-08 08:18:39 +03:00
|
|
|
// Make sure we drop our cached style contexts before the presshell arena
|
|
|
|
// starts going away.
|
|
|
|
ClearNonInheritingStyleContexts();
|
2016-01-27 05:02:04 +03:00
|
|
|
mRawSet = nullptr;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
2017-04-06 05:22:36 +03:00
|
|
|
size_t
|
|
|
|
ServoStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
|
|
{
|
|
|
|
size_t n = aMallocSizeOf(this);
|
|
|
|
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
|
|
// worthwhile:
|
|
|
|
// - mRawSet
|
|
|
|
// - mSheets
|
|
|
|
// - mNonInheritingStyleContexts
|
|
|
|
//
|
|
|
|
// The following members are not measured:
|
|
|
|
// - mPresContext, because it a non-owning pointer
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:10 +03:00
|
|
|
bool
|
|
|
|
ServoStyleSet::GetAuthorStyleDisabled() const
|
|
|
|
{
|
2017-04-11 10:43:14 +03:00
|
|
|
return mAuthorStyleDisabled;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled)
|
|
|
|
{
|
2017-04-11 10:43:14 +03:00
|
|
|
if (mAuthorStyleDisabled == aStyleDisabled) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
mAuthorStyleDisabled = aStyleDisabled;
|
|
|
|
|
|
|
|
// If we've just disabled, we have to note the stylesheets have changed and
|
|
|
|
// call flush directly, since the PresShell won't.
|
|
|
|
if (mAuthorStyleDisabled) {
|
|
|
|
NoteStyleSheetsChanged();
|
|
|
|
Servo_StyleSet_FlushStyleSheets(mRawSet.get());
|
|
|
|
}
|
|
|
|
// If we've just enabled, then PresShell will trigger the notification and
|
|
|
|
// later flush when the stylesheet objects are enabled in JS.
|
|
|
|
|
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ServoStyleSet::BeginUpdate()
|
|
|
|
{
|
2016-02-24 10:01:12 +03:00
|
|
|
++mBatching;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::EndUpdate()
|
|
|
|
{
|
2016-02-24 10:01:12 +03:00
|
|
|
MOZ_ASSERT(mBatching > 0);
|
|
|
|
if (--mBatching > 0) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-12-22 02:33:24 +03:00
|
|
|
Servo_StyleSet_FlushStyleSheets(mRawSet.get());
|
2016-02-24 10:01:12 +03:00
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
|
|
|
ServoStyleSet::ResolveStyleFor(Element* aElement,
|
2016-11-02 09:11:24 +03:00
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
LazyComputeBehavior aMayCompute)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-04-29 07:04:16 +03:00
|
|
|
return GetContext(aElement, aParentContext, nullptr,
|
2017-01-06 00:12:53 +03:00
|
|
|
CSSPseudoElementType::NotPseudo, aMayCompute);
|
2016-04-29 07:04:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
|
|
|
ServoStyleSet::GetContext(nsIContent* aContent,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
nsIAtom* aPseudoTag,
|
2016-11-02 09:11:24 +03:00
|
|
|
CSSPseudoElementType aPseudoType,
|
|
|
|
LazyComputeBehavior aMayCompute)
|
2016-04-29 07:04:16 +03:00
|
|
|
{
|
2016-11-02 09:11:24 +03:00
|
|
|
MOZ_ASSERT(aContent->IsElement());
|
|
|
|
Element* element = aContent->AsElement();
|
2016-12-28 10:49:12 +03:00
|
|
|
|
|
|
|
RefPtr<ServoComputedValues> computedValues;
|
|
|
|
if (aMayCompute == LazyComputeBehavior::Allow) {
|
2017-04-12 05:05:26 +03:00
|
|
|
PreTraverseSync();
|
2017-03-08 23:20:17 +03:00
|
|
|
computedValues = ResolveStyleLazily(element, nullptr);
|
2016-12-28 10:49:12 +03:00
|
|
|
} else {
|
2017-01-06 00:12:53 +03:00
|
|
|
computedValues = ResolveServoStyle(element);
|
2016-12-28 10:49:12 +03:00
|
|
|
}
|
|
|
|
|
2016-03-18 23:14:07 +03:00
|
|
|
MOZ_ASSERT(computedValues);
|
2017-01-29 06:59:00 +03:00
|
|
|
return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType,
|
|
|
|
element);
|
2016-04-29 03:56:37 +03:00
|
|
|
}
|
2016-03-18 23:14:07 +03:00
|
|
|
|
2016-04-29 03:56:37 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
|
|
|
ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
nsIAtom* aPseudoTag,
|
2017-01-29 06:59:00 +03:00
|
|
|
CSSPseudoElementType aPseudoType,
|
|
|
|
Element* aElementForAnimation)
|
2016-04-29 03:56:37 +03:00
|
|
|
{
|
2016-03-18 23:14:07 +03:00
|
|
|
// XXXbholley: nsStyleSet does visited handling here.
|
|
|
|
|
|
|
|
// XXXbholley: Figure out the correct thing to pass here. Does this fixup
|
|
|
|
// duplicate something that servo already does?
|
2017-03-09 07:41:04 +03:00
|
|
|
// See bug 1344914.
|
2016-03-18 23:14:07 +03:00
|
|
|
bool skipFixup = false;
|
|
|
|
|
2017-03-26 23:53:34 +03:00
|
|
|
RefPtr<nsStyleContext> result = NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
|
|
|
|
aPseudoType, Move(aComputedValues), skipFixup);
|
|
|
|
|
|
|
|
// Set the body color on the pres context. See nsStyleSet::GetContext
|
|
|
|
if (aElementForAnimation &&
|
|
|
|
aElementForAnimation->IsHTMLElement(nsGkAtoms::body) &&
|
|
|
|
aPseudoType == CSSPseudoElementType::NotPseudo &&
|
|
|
|
mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
|
|
|
|
nsIDocument* doc = aElementForAnimation->GetUncomposedDoc();
|
|
|
|
if (doc && doc->GetBodyElement() == aElementForAnimation) {
|
|
|
|
// Update the prescontext's body color
|
|
|
|
mPresContext->SetBodyTextColor(result->StyleColor()->mColor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.forget();
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
2017-01-20 02:56:53 +03:00
|
|
|
void
|
|
|
|
ServoStyleSet::ResolveMappedAttrDeclarationBlocks()
|
|
|
|
{
|
|
|
|
if (nsHTMLStyleSheet* sheet = mPresContext->Document()->GetAttributeStyleSheet()) {
|
2017-04-08 17:42:43 +03:00
|
|
|
sheet->CalculateMappedServoDeclarations(mPresContext);
|
2017-01-20 02:56:53 +03:00
|
|
|
}
|
2017-02-23 04:19:04 +03:00
|
|
|
|
|
|
|
mPresContext->Document()->ResolveScheduledSVGPresAttrs();
|
2017-01-20 02:56:53 +03:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:20:17 +03:00
|
|
|
void
|
2017-03-17 00:10:22 +03:00
|
|
|
ServoStyleSet::PreTraverseSync()
|
2017-03-08 23:20:17 +03:00
|
|
|
{
|
2017-01-20 02:56:53 +03:00
|
|
|
ResolveMappedAttrDeclarationBlocks();
|
2017-02-02 22:48:28 +03:00
|
|
|
|
2017-03-17 00:10:22 +03:00
|
|
|
// This is lazily computed and pseudo matching needs to access
|
|
|
|
// it so force computation early.
|
|
|
|
mPresContext->Document()->GetDocumentState();
|
2017-04-08 01:49:44 +03:00
|
|
|
|
|
|
|
// Ensure that the @font-face data is not stale
|
|
|
|
mPresContext->Document()->GetUserFontSet();
|
2017-03-17 00:10:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-04-04 14:34:30 +03:00
|
|
|
ServoStyleSet::PreTraverse(Element* aRoot)
|
2017-03-17 00:10:22 +03:00
|
|
|
{
|
|
|
|
PreTraverseSync();
|
|
|
|
|
2017-03-08 23:20:17 +03:00
|
|
|
// Process animation stuff that we should avoid doing during the parallel
|
|
|
|
// traversal.
|
2017-04-04 14:34:30 +03:00
|
|
|
if (aRoot) {
|
|
|
|
mPresContext->EffectCompositor()->PreTraverseInSubtree(aRoot);
|
|
|
|
} else {
|
|
|
|
mPresContext->EffectCompositor()->PreTraverse();
|
|
|
|
}
|
2017-03-08 23:20:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ServoStyleSet::PrepareAndTraverseSubtree(RawGeckoElementBorrowed aRoot,
|
2017-04-08 17:57:08 +03:00
|
|
|
TraversalRootBehavior aRootBehavior,
|
|
|
|
TraversalRestyleBehavior
|
|
|
|
aRestyleBehavior)
|
2017-03-08 23:20:17 +03:00
|
|
|
{
|
2017-02-03 01:03:46 +03:00
|
|
|
// Get the Document's root element to ensure that the cache is valid before
|
|
|
|
// calling into the (potentially-parallel) Servo traversal, where a cache hit
|
|
|
|
// is necessary to avoid a data race when updating the cache.
|
|
|
|
mozilla::Unused << aRoot->OwnerDoc()->GetRootElement();
|
|
|
|
|
2017-02-02 22:48:28 +03:00
|
|
|
MOZ_ASSERT(!sInServoTraversal);
|
|
|
|
sInServoTraversal = true;
|
2017-03-24 01:21:18 +03:00
|
|
|
|
|
|
|
bool isInitial = !aRoot->HasServoData();
|
2017-04-04 14:34:30 +03:00
|
|
|
bool forReconstruct =
|
|
|
|
aRestyleBehavior == TraversalRestyleBehavior::ForReconstruct;
|
2017-02-10 05:42:30 +03:00
|
|
|
bool postTraversalRequired =
|
2017-04-08 17:57:08 +03:00
|
|
|
Servo_TraverseSubtree(aRoot, mRawSet.get(), aRootBehavior, aRestyleBehavior);
|
2017-04-04 14:34:30 +03:00
|
|
|
MOZ_ASSERT_IF(isInitial || forReconstruct, !postTraversalRequired);
|
|
|
|
|
|
|
|
auto root = const_cast<Element*>(aRoot);
|
2017-03-10 05:53:19 +03:00
|
|
|
|
|
|
|
// If there are still animation restyles needed, trigger a second traversal to
|
|
|
|
// update CSS animations' styles.
|
2017-04-04 14:34:30 +03:00
|
|
|
EffectCompositor* compositor = mPresContext->EffectCompositor();
|
|
|
|
if (forReconstruct ? compositor->PreTraverseInSubtree(root)
|
|
|
|
: compositor->PreTraverse()) {
|
2017-04-08 17:57:08 +03:00
|
|
|
if (Servo_TraverseSubtree(aRoot, mRawSet.get(),
|
|
|
|
aRootBehavior, aRestyleBehavior)) {
|
2017-04-04 14:34:30 +03:00
|
|
|
MOZ_ASSERT(!forReconstruct);
|
2017-03-24 01:21:18 +03:00
|
|
|
if (isInitial) {
|
|
|
|
// We're doing initial styling, and the additional animation
|
|
|
|
// traversal changed the styles that were set by the first traversal.
|
|
|
|
// This would normally require a post-traversal to update the style
|
|
|
|
// contexts, and the DOM now has dirty descendant bits and RestyleData
|
|
|
|
// in expectation of that post-traversal. But since this is actually
|
|
|
|
// the initial styling, there are no style contexts to update and no
|
|
|
|
// frames to apply the change hints to, so we don't need to do that
|
|
|
|
// post-traversal. Instead, just drop this state and tell the caller
|
|
|
|
// that no post-traversal is required.
|
|
|
|
MOZ_ASSERT(!postTraversalRequired);
|
2017-04-04 14:34:30 +03:00
|
|
|
ServoRestyleManager::ClearRestyleStateFromSubtree(root);
|
2017-03-24 01:21:18 +03:00
|
|
|
} else {
|
|
|
|
postTraversalRequired = true;
|
|
|
|
}
|
|
|
|
}
|
2017-03-10 05:53:19 +03:00
|
|
|
}
|
|
|
|
|
2017-02-02 22:48:28 +03:00
|
|
|
sInServoTraversal = false;
|
2017-02-10 05:42:30 +03:00
|
|
|
return postTraversalRequired;
|
2017-01-20 02:56:53 +03:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:10 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
|
|
|
ServoStyleSet::ResolveStyleFor(Element* aElement,
|
|
|
|
nsStyleContext* aParentContext,
|
2016-11-02 09:11:24 +03:00
|
|
|
LazyComputeBehavior aMayCompute,
|
2016-02-24 10:01:10 +03:00
|
|
|
TreeMatchContext& aTreeMatchContext)
|
|
|
|
{
|
2016-04-27 05:34:49 +03:00
|
|
|
// aTreeMatchContext is used to speed up selector matching,
|
|
|
|
// but if the element already has a ServoComputedValues computed in
|
|
|
|
// advance, then we shouldn't need to use it.
|
2017-01-06 00:12:53 +03:00
|
|
|
return ResolveStyleFor(aElement, aParentContext, aMayCompute);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
2016-04-29 07:01:44 +03:00
|
|
|
ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
|
|
|
|
nsStyleContext* aParentContext)
|
|
|
|
{
|
2016-04-29 07:04:16 +03:00
|
|
|
MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
|
2016-08-12 21:30:29 +03:00
|
|
|
MOZ_ASSERT(aTextNode->GetParent());
|
2016-10-26 02:27:08 +03:00
|
|
|
MOZ_ASSERT(aParentContext);
|
|
|
|
|
|
|
|
// Gecko expects text node style contexts to be like elements that match no
|
|
|
|
// rules: inherit the inherit structs, reset the reset structs. This is cheap
|
|
|
|
// enough to do on the main thread, which means that the parallel style system
|
|
|
|
// can avoid worrying about text nodes.
|
|
|
|
const ServoComputedValues* parentComputedValues =
|
|
|
|
aParentContext->StyleSource().AsServoComputedValues();
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2017-01-04 22:52:27 +03:00
|
|
|
Servo_ComputedValues_Inherit(mRawSet.get(), parentComputedValues).Consume();
|
2016-08-12 21:30:29 +03:00
|
|
|
|
|
|
|
return GetContext(computedValues.forget(), aParentContext,
|
2017-03-09 07:41:04 +03:00
|
|
|
nsCSSAnonBoxes::mozText,
|
|
|
|
CSSPseudoElementType::InheritingAnonBox,
|
2017-01-29 06:59:00 +03:00
|
|
|
nullptr);
|
2016-04-29 07:01:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
2017-03-08 08:18:32 +03:00
|
|
|
ServoStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2017-03-08 08:18:32 +03:00
|
|
|
const ServoComputedValues* parent = aParentContext->StyleSource().AsServoComputedValues();
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
|
|
|
Servo_ComputedValues_Inherit(mRawSet.get(), parent).Consume();
|
|
|
|
MOZ_ASSERT(computedValues);
|
|
|
|
|
|
|
|
return GetContext(computedValues.forget(), aParentContext,
|
|
|
|
nsCSSAnonBoxes::firstLetterContinuation,
|
2017-03-09 07:41:04 +03:00
|
|
|
CSSPseudoElementType::InheritingAnonBox,
|
2017-03-08 08:18:32 +03:00
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
2017-03-08 08:18:40 +03:00
|
|
|
ServoStyleSet::ResolveStyleForPlaceholder()
|
2017-03-08 08:18:32 +03:00
|
|
|
{
|
2017-03-08 08:18:40 +03:00
|
|
|
RefPtr<nsStyleContext>& cache =
|
2017-03-09 07:39:45 +03:00
|
|
|
mNonInheritingStyleContexts[nsCSSAnonBoxes::NonInheriting::oofPlaceholder];
|
2017-03-08 08:18:40 +03:00
|
|
|
if (cache) {
|
|
|
|
RefPtr<nsStyleContext> retval = cache;
|
|
|
|
return retval.forget();
|
|
|
|
}
|
|
|
|
|
2016-08-12 21:30:29 +03:00
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2017-03-08 08:18:40 +03:00
|
|
|
Servo_ComputedValues_Inherit(mRawSet.get(), nullptr).Consume();
|
2016-05-06 01:32:00 +03:00
|
|
|
MOZ_ASSERT(computedValues);
|
|
|
|
|
2017-03-08 08:18:40 +03:00
|
|
|
RefPtr<nsStyleContext> retval =
|
|
|
|
GetContext(computedValues.forget(), nullptr,
|
|
|
|
nsCSSAnonBoxes::oofPlaceholder,
|
2017-03-09 07:41:04 +03:00
|
|
|
CSSPseudoElementType::NonInheritingAnonBox,
|
2017-03-08 08:18:40 +03:00
|
|
|
nullptr);
|
|
|
|
cache = retval;
|
|
|
|
return retval.forget();
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
2016-12-22 04:58:38 +03:00
|
|
|
ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
|
2016-02-24 10:01:10 +03:00
|
|
|
CSSPseudoElementType aType,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
Element* aPseudoElement)
|
|
|
|
{
|
2016-05-05 03:59:10 +03:00
|
|
|
if (aPseudoElement) {
|
2017-02-14 10:26:10 +03:00
|
|
|
NS_WARNING("stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
|
2016-05-05 03:59:10 +03:00
|
|
|
}
|
2016-12-22 04:58:38 +03:00
|
|
|
|
|
|
|
// NB: We ignore aParentContext, on the assumption that pseudo element styles
|
|
|
|
// should just inherit from aOriginatingElement's primary style, which Servo
|
|
|
|
// already knows.
|
2016-04-29 03:56:37 +03:00
|
|
|
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
|
|
|
|
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
|
|
|
|
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2016-12-22 04:58:38 +03:00
|
|
|
Servo_ResolvePseudoStyle(aOriginatingElement, pseudoTag,
|
|
|
|
/* is_probe = */ false, mRawSet.get()).Consume();
|
2016-04-29 03:56:37 +03:00
|
|
|
MOZ_ASSERT(computedValues);
|
|
|
|
|
2017-01-29 06:59:00 +03:00
|
|
|
bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
|
|
|
|
aType == CSSPseudoElementType::after;
|
|
|
|
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
|
|
|
|
isBeforeOrAfter ? aOriginatingElement : nullptr);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
2016-12-28 10:49:12 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
|
|
|
ServoStyleSet::ResolveTransientStyle(Element* aElement, CSSPseudoElementType aType)
|
|
|
|
{
|
2017-04-15 01:37:34 +03:00
|
|
|
PreTraverseSync();
|
|
|
|
|
2016-12-28 10:49:12 +03:00
|
|
|
nsIAtom* pseudoTag = nullptr;
|
|
|
|
if (aType != CSSPseudoElementType::NotPseudo) {
|
|
|
|
pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2017-03-08 23:20:17 +03:00
|
|
|
ResolveStyleLazily(aElement, pseudoTag);
|
2016-12-28 10:49:12 +03:00
|
|
|
|
2017-01-29 06:59:00 +03:00
|
|
|
return GetContext(computedValues.forget(), nullptr, pseudoTag, aType,
|
|
|
|
nullptr);
|
2016-12-28 10:49:12 +03:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:10 +03:00
|
|
|
// aFlags is an nsStyleSet flags bitfield
|
|
|
|
already_AddRefed<nsStyleContext>
|
2017-03-09 07:50:28 +03:00
|
|
|
ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
uint32_t aFlags)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2017-03-09 07:41:04 +03:00
|
|
|
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
|
|
|
|
!nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
|
2016-02-26 04:51:02 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(aFlags == 0 ||
|
|
|
|
aFlags == nsStyleSet::eSkipParentDisplayBasedStyleFixup);
|
2016-03-18 23:14:07 +03:00
|
|
|
bool skipFixup = aFlags & nsStyleSet::eSkipParentDisplayBasedStyleFixup;
|
|
|
|
|
2016-10-18 07:29:03 +03:00
|
|
|
const ServoComputedValues* parentStyle =
|
2016-03-18 23:14:07 +03:00
|
|
|
aParentContext ? aParentContext->StyleSource().AsServoComputedValues()
|
|
|
|
: nullptr;
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2017-03-13 19:53:45 +03:00
|
|
|
Servo_ComputedValues_GetForAnonymousBox(parentStyle, aPseudoTag, skipFixup,
|
2016-08-23 06:14:27 +03:00
|
|
|
mRawSet.get()).Consume();
|
2016-07-28 06:03:49 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (!computedValues) {
|
|
|
|
nsString pseudo;
|
|
|
|
aPseudoTag->ToString(pseudo);
|
|
|
|
NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
|
|
|
|
NS_ConvertUTF16toUTF8(pseudo).get()).get());
|
|
|
|
MOZ_CRASH();
|
|
|
|
}
|
|
|
|
#endif
|
2016-03-18 23:14:07 +03:00
|
|
|
|
2017-03-09 07:41:04 +03:00
|
|
|
// FIXME(bz, bug 1344914) We should really GetContext here and make skipFixup
|
|
|
|
// work there.
|
2016-05-05 05:33:00 +03:00
|
|
|
return NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
|
2017-03-09 07:41:04 +03:00
|
|
|
CSSPseudoElementType::InheritingAnonBox,
|
2016-03-18 23:14:07 +03:00
|
|
|
computedValues.forget(), skipFixup);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
2017-03-09 07:41:04 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
|
|
|
ServoStyleSet::ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
|
|
|
|
nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
|
|
|
|
MOZ_ASSERT(aPseudoTag != nsCSSAnonBoxes::pageContent,
|
|
|
|
"If nsCSSAnonBoxes::pageContent ends up non-inheriting, check "
|
|
|
|
"whether we need to do anything to move the "
|
2017-03-09 07:50:28 +03:00
|
|
|
"@page handling from ResolveInheritingAnonymousBoxStyle to "
|
2017-03-09 07:41:04 +03:00
|
|
|
"ResolveNonInheritingAnonymousBoxStyle");
|
|
|
|
|
|
|
|
nsCSSAnonBoxes::NonInheriting type =
|
|
|
|
nsCSSAnonBoxes::NonInheritingTypeForPseudoTag(aPseudoTag);
|
|
|
|
RefPtr<nsStyleContext>& cache = mNonInheritingStyleContexts[type];
|
|
|
|
if (cache) {
|
|
|
|
RefPtr<nsStyleContext> retval = cache;
|
|
|
|
return retval.forget();
|
|
|
|
}
|
|
|
|
|
2017-03-13 19:53:45 +03:00
|
|
|
// We always want to skip parent-based display fixup here. It never makes
|
|
|
|
// sense for non-inheriting anonymous boxes.
|
|
|
|
MOZ_ASSERT(!nsCSSAnonBoxes::IsNonInheritingAnonBox(nsCSSAnonBoxes::viewport),
|
|
|
|
"viewport needs fixup to handle blockifying it");
|
2017-03-09 07:41:04 +03:00
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2017-03-13 19:53:45 +03:00
|
|
|
Servo_ComputedValues_GetForAnonymousBox(nullptr, aPseudoTag, true,
|
2017-03-09 07:41:04 +03:00
|
|
|
mRawSet.get()).Consume();
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (!computedValues) {
|
|
|
|
nsString pseudo;
|
|
|
|
aPseudoTag->ToString(pseudo);
|
|
|
|
NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
|
|
|
|
NS_ConvertUTF16toUTF8(pseudo).get()).get());
|
|
|
|
MOZ_CRASH();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RefPtr<nsStyleContext> retval =
|
|
|
|
GetContext(computedValues.forget(), nullptr, aPseudoTag,
|
|
|
|
CSSPseudoElementType::NonInheritingAnonBox, nullptr);
|
|
|
|
cache = retval;
|
|
|
|
return retval.forget();
|
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:10 +03:00
|
|
|
// manage the set of style sheets in the style set
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::AppendStyleSheet(SheetType aType,
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSheet* aSheet)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-02-26 04:51:02 +03:00
|
|
|
MOZ_ASSERT(aSheet);
|
|
|
|
MOZ_ASSERT(aSheet->IsApplicable());
|
|
|
|
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
|
|
|
|
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(aSheet->RawSheet(), "Raw sheet should be in place before insertion.");
|
2016-02-26 04:51:02 +03:00
|
|
|
mSheets[aType].RemoveElement(aSheet);
|
|
|
|
mSheets[aType].AppendElement(aSheet);
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
// Maintain a mirrored list of sheets on the servo side.
|
|
|
|
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet->RawSheet(), !mBatching);
|
|
|
|
}
|
2016-02-26 05:57:42 +03:00
|
|
|
|
2016-02-26 04:51:02 +03:00
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::PrependStyleSheet(SheetType aType,
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSheet* aSheet)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-02-26 04:51:02 +03:00
|
|
|
MOZ_ASSERT(aSheet);
|
|
|
|
MOZ_ASSERT(aSheet->IsApplicable());
|
|
|
|
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
|
|
|
|
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(aSheet->RawSheet(), "Raw sheet should be in place before insertion.");
|
2016-02-26 04:51:02 +03:00
|
|
|
mSheets[aType].RemoveElement(aSheet);
|
|
|
|
mSheets[aType].InsertElementAt(0, aSheet);
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
// Maintain a mirrored list of sheets on the servo side.
|
|
|
|
Servo_StyleSet_PrependStyleSheet(mRawSet.get(), aSheet->RawSheet(), !mBatching);
|
|
|
|
}
|
2016-02-26 05:57:42 +03:00
|
|
|
|
2016-02-26 04:51:02 +03:00
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::RemoveStyleSheet(SheetType aType,
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSheet* aSheet)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-02-26 05:57:42 +03:00
|
|
|
MOZ_ASSERT(aSheet);
|
|
|
|
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
|
|
|
|
|
|
|
|
mSheets[aType].RemoveElement(aSheet);
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
// Maintain a mirrored list of sheets on the servo side.
|
|
|
|
Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), aSheet->RawSheet(), !mBatching);
|
|
|
|
}
|
2016-02-26 05:57:42 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::ReplaceSheets(SheetType aType,
|
2016-02-24 10:01:12 +03:00
|
|
|
const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-08-03 07:08:01 +03:00
|
|
|
// Gecko uses a two-dimensional array keyed by sheet type, whereas Servo
|
|
|
|
// stores a flattened list. This makes ReplaceSheets a pretty clunky thing
|
|
|
|
// to express. If the need ever arises, we can easily make this more efficent,
|
|
|
|
// probably by aligning the representations better between engines.
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
for (ServoStyleSheet* sheet : mSheets[aType]) {
|
|
|
|
Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), sheet->RawSheet(), false);
|
|
|
|
}
|
2016-08-03 07:08:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mSheets[aType].Clear();
|
|
|
|
mSheets[aType].AppendElements(aNewSheets);
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
for (ServoStyleSheet* sheet : mSheets[aType]) {
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(sheet->RawSheet(), "Raw sheet should be in place before replacement.");
|
2017-01-04 22:52:26 +03:00
|
|
|
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet->RawSheet(), false);
|
|
|
|
}
|
2016-12-22 02:33:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!mBatching) {
|
|
|
|
Servo_StyleSet_FlushStyleSheets(mRawSet.get());
|
2016-08-03 07:08:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoStyleSet::InsertStyleSheetBefore(SheetType aType,
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSheet* aNewSheet,
|
|
|
|
ServoStyleSheet* aReferenceSheet)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-04-29 07:01:44 +03:00
|
|
|
MOZ_ASSERT(aNewSheet);
|
|
|
|
MOZ_ASSERT(aReferenceSheet);
|
|
|
|
MOZ_ASSERT(aNewSheet->IsApplicable());
|
|
|
|
|
|
|
|
mSheets[aType].RemoveElement(aNewSheet);
|
|
|
|
size_t idx = mSheets[aType].IndexOf(aReferenceSheet);
|
|
|
|
if (idx == mSheets[aType].NoIndex) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(aReferenceSheet->RawSheet(), "Reference sheet should have a raw sheet.");
|
2016-04-29 07:01:44 +03:00
|
|
|
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(aNewSheet->RawSheet(), "Raw sheet should be in place before insertion.");
|
2016-04-29 07:01:44 +03:00
|
|
|
mSheets[aType].InsertElementAt(idx, aNewSheet);
|
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
// Maintain a mirrored list of sheets on the servo side.
|
|
|
|
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aNewSheet->RawSheet(),
|
|
|
|
aReferenceSheet->RawSheet(), !mBatching);
|
|
|
|
}
|
2016-04-29 07:01:44 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
ServoStyleSet::SheetCount(SheetType aType) const
|
|
|
|
{
|
2016-02-26 04:51:02 +03:00
|
|
|
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
|
|
|
|
return mSheets[aType].Length();
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSheet*
|
2016-02-24 10:01:10 +03:00
|
|
|
ServoStyleSet::StyleSheetAt(SheetType aType,
|
|
|
|
int32_t aIndex) const
|
|
|
|
{
|
2016-02-26 04:51:02 +03:00
|
|
|
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
|
|
|
|
return mSheets[aType][aIndex];
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSet::RemoveDocStyleSheet(ServoStyleSheet* aSheet)
|
2016-02-24 10:01:10 +03:00
|
|
|
{
|
2016-04-29 07:01:44 +03:00
|
|
|
return RemoveStyleSheet(SheetType::Doc, aSheet);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2016-02-24 10:01:12 +03:00
|
|
|
ServoStyleSet::AddDocStyleSheet(ServoStyleSheet* aSheet,
|
2016-02-24 10:01:10 +03:00
|
|
|
nsIDocument* aDocument)
|
|
|
|
{
|
2017-01-09 12:42:52 +03:00
|
|
|
MOZ_ASSERT(aSheet->IsApplicable());
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(aSheet->RawSheet(), "Raw sheet should be in place by this point.");
|
2017-01-09 12:42:52 +03:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> strong(aSheet);
|
2016-04-29 07:01:44 +03:00
|
|
|
|
2017-02-15 23:25:21 +03:00
|
|
|
nsTArray<RefPtr<ServoStyleSheet>>& sheetsArray = mSheets[SheetType::Doc];
|
|
|
|
|
|
|
|
sheetsArray.RemoveElement(aSheet);
|
2016-04-29 07:01:44 +03:00
|
|
|
|
|
|
|
size_t index =
|
2017-02-15 23:25:21 +03:00
|
|
|
aDocument->FindDocStyleSheetInsertionPoint(sheetsArray, aSheet);
|
|
|
|
sheetsArray.InsertElementAt(index, aSheet);
|
2016-04-29 07:01:44 +03:00
|
|
|
|
2017-01-04 22:52:26 +03:00
|
|
|
if (mRawSet) {
|
|
|
|
// Maintain a mirrored list of sheets on the servo side.
|
2017-02-15 23:25:21 +03:00
|
|
|
ServoStyleSheet* followingSheet = sheetsArray.SafeElementAt(index + 1);
|
2017-01-04 22:52:26 +03:00
|
|
|
if (followingSheet) {
|
2017-02-15 23:25:21 +03:00
|
|
|
MOZ_ASSERT(followingSheet->RawSheet(), "Every mSheets element should have a raw sheet");
|
2017-01-04 22:52:26 +03:00
|
|
|
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aSheet->RawSheet(),
|
|
|
|
followingSheet->RawSheet(), !mBatching);
|
|
|
|
} else {
|
|
|
|
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet->RawSheet(), !mBatching);
|
|
|
|
}
|
2016-04-29 07:01:44 +03:00
|
|
|
}
|
|
|
|
|
2016-02-26 05:57:42 +03:00
|
|
|
return NS_OK;
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
2016-12-22 04:58:38 +03:00
|
|
|
ServoStyleSet::ProbePseudoElementStyle(Element* aOriginatingElement,
|
2016-02-24 10:01:10 +03:00
|
|
|
CSSPseudoElementType aType,
|
|
|
|
nsStyleContext* aParentContext)
|
|
|
|
{
|
2016-12-22 04:58:38 +03:00
|
|
|
// NB: We ignore aParentContext, on the assumption that pseudo element styles
|
|
|
|
// should just inherit from aOriginatingElement's primary style, which Servo
|
|
|
|
// already knows.
|
2016-04-29 03:56:37 +03:00
|
|
|
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
|
|
|
|
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
|
|
|
|
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
2016-12-22 04:58:38 +03:00
|
|
|
Servo_ResolvePseudoStyle(aOriginatingElement, pseudoTag,
|
|
|
|
/* is_probe = */ true, mRawSet.get()).Consume();
|
2016-04-29 03:56:37 +03:00
|
|
|
if (!computedValues) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For :before and :after pseudo-elements, having display: none or no
|
|
|
|
// 'content' property is equivalent to not having the pseudo-element
|
|
|
|
// at all.
|
2017-01-29 06:59:00 +03:00
|
|
|
bool isBeforeOrAfter = pseudoTag == nsCSSPseudoElements::before ||
|
|
|
|
pseudoTag == nsCSSPseudoElements::after;
|
|
|
|
if (isBeforeOrAfter) {
|
2016-04-29 03:56:37 +03:00
|
|
|
const nsStyleDisplay *display = Servo_GetStyleDisplay(computedValues);
|
|
|
|
const nsStyleContent *content = Servo_GetStyleContent(computedValues);
|
|
|
|
// XXXldb What is contentCount for |content: ""|?
|
2016-09-03 21:46:58 +03:00
|
|
|
if (display->mDisplay == StyleDisplay::None ||
|
2016-04-29 03:56:37 +03:00
|
|
|
content->ContentCount() == 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 06:59:00 +03:00
|
|
|
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
|
|
|
|
isBeforeOrAfter ? aOriginatingElement : nullptr);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext>
|
2016-12-22 04:58:38 +03:00
|
|
|
ServoStyleSet::ProbePseudoElementStyle(Element* aOriginatingElement,
|
2016-02-24 10:01:10 +03:00
|
|
|
CSSPseudoElementType aType,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
TreeMatchContext& aTreeMatchContext,
|
|
|
|
Element* aPseudoElement)
|
|
|
|
{
|
2016-05-05 03:59:10 +03:00
|
|
|
if (aPseudoElement) {
|
|
|
|
NS_ERROR("stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
|
|
|
|
}
|
2016-12-22 04:58:38 +03:00
|
|
|
return ProbePseudoElementStyle(aOriginatingElement, aType, aParentContext);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRestyleHint
|
|
|
|
ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
|
|
|
|
EventStates aStateMask)
|
|
|
|
{
|
2016-07-29 01:22:54 +03:00
|
|
|
NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
|
2016-07-14 00:37:56 +03:00
|
|
|
return nsRestyleHint(0);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRestyleHint
|
|
|
|
ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
|
|
|
|
CSSPseudoElementType aPseudoType,
|
|
|
|
dom::Element* aPseudoElement,
|
|
|
|
EventStates aStateMask)
|
|
|
|
{
|
2016-07-29 01:22:54 +03:00
|
|
|
NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
|
2016-07-14 00:37:56 +03:00
|
|
|
return nsRestyleHint(0);
|
2016-02-24 10:01:10 +03:00
|
|
|
}
|
2016-05-25 09:55:49 +03:00
|
|
|
|
2017-02-10 05:42:30 +03:00
|
|
|
bool
|
2016-11-02 09:11:24 +03:00
|
|
|
ServoStyleSet::StyleDocument()
|
2016-08-12 00:12:49 +03:00
|
|
|
{
|
2017-03-08 23:20:17 +03:00
|
|
|
PreTraverse();
|
|
|
|
|
2016-12-01 11:19:50 +03:00
|
|
|
// Restyle the document from the root element and each of the document level
|
|
|
|
// NAC subtree roots.
|
2017-02-10 05:42:30 +03:00
|
|
|
bool postTraversalRequired = false;
|
2016-12-01 11:19:50 +03:00
|
|
|
DocumentStyleRootIterator iter(mPresContext->Document());
|
|
|
|
while (Element* root = iter.GetNextStyleRoot()) {
|
2017-04-08 17:57:08 +03:00
|
|
|
if (PrepareAndTraverseSubtree(root,
|
|
|
|
TraversalRootBehavior::Normal,
|
|
|
|
TraversalRestyleBehavior::Normal)) {
|
2017-02-10 05:42:30 +03:00
|
|
|
postTraversalRequired = true;
|
2016-12-01 11:19:50 +03:00
|
|
|
}
|
|
|
|
}
|
2017-02-10 05:42:30 +03:00
|
|
|
return postTraversalRequired;
|
2016-08-12 00:12:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-12-11 09:11:36 +03:00
|
|
|
ServoStyleSet::StyleNewSubtree(Element* aRoot)
|
2016-08-12 00:12:49 +03:00
|
|
|
{
|
2016-12-11 09:11:36 +03:00
|
|
|
MOZ_ASSERT(!aRoot->HasServoData());
|
2017-03-08 23:20:17 +03:00
|
|
|
|
|
|
|
PreTraverse();
|
|
|
|
|
2017-02-10 05:42:30 +03:00
|
|
|
DebugOnly<bool> postTraversalRequired =
|
2017-04-08 17:57:08 +03:00
|
|
|
PrepareAndTraverseSubtree(aRoot,
|
|
|
|
TraversalRootBehavior::Normal,
|
|
|
|
TraversalRestyleBehavior::Normal);
|
2017-02-10 05:42:30 +03:00
|
|
|
MOZ_ASSERT(!postTraversalRequired);
|
2016-08-12 00:12:49 +03:00
|
|
|
}
|
|
|
|
|
2016-05-25 09:55:49 +03:00
|
|
|
void
|
2016-12-11 09:11:36 +03:00
|
|
|
ServoStyleSet::StyleNewChildren(Element* aParent)
|
2016-05-25 09:55:49 +03:00
|
|
|
{
|
2017-03-08 23:20:17 +03:00
|
|
|
PreTraverse();
|
|
|
|
|
2017-04-08 17:57:08 +03:00
|
|
|
PrepareAndTraverseSubtree(aParent,
|
|
|
|
TraversalRootBehavior::UnstyledChildrenOnly,
|
|
|
|
TraversalRestyleBehavior::Normal);
|
2017-02-10 05:42:30 +03:00
|
|
|
// We can't assert that Servo_TraverseSubtree returns false, since aParent
|
|
|
|
// or some of its other children might have pending restyles.
|
2016-11-02 09:11:24 +03:00
|
|
|
}
|
|
|
|
|
2017-04-04 14:34:30 +03:00
|
|
|
void
|
|
|
|
ServoStyleSet::StyleSubtreeForReconstruct(Element* aRoot)
|
|
|
|
{
|
|
|
|
PreTraverse(aRoot);
|
|
|
|
|
|
|
|
DebugOnly<bool> postTraversalRequired =
|
|
|
|
PrepareAndTraverseSubtree(aRoot,
|
|
|
|
TraversalRootBehavior::Normal,
|
|
|
|
TraversalRestyleBehavior::ForReconstruct);
|
|
|
|
MOZ_ASSERT(!postTraversalRequired);
|
|
|
|
}
|
|
|
|
|
2016-12-19 09:30:14 +03:00
|
|
|
void
|
|
|
|
ServoStyleSet::NoteStyleSheetsChanged()
|
|
|
|
{
|
2017-04-11 10:59:44 +03:00
|
|
|
Servo_StyleSet_NoteStyleSheetsChanged(mRawSet.get(), mAuthorStyleDisabled);
|
2016-12-19 09:30:14 +03:00
|
|
|
}
|
|
|
|
|
2016-11-02 09:11:24 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
void
|
|
|
|
ServoStyleSet::AssertTreeIsClean()
|
|
|
|
{
|
2016-12-28 11:26:10 +03:00
|
|
|
DocumentStyleRootIterator iter(mPresContext->Document());
|
|
|
|
while (Element* root = iter.GetNextStyleRoot()) {
|
2016-11-02 09:11:24 +03:00
|
|
|
Servo_AssertTreeIsClean(root);
|
|
|
|
}
|
2016-05-25 09:55:49 +03:00
|
|
|
}
|
2016-11-02 09:11:24 +03:00
|
|
|
#endif
|
2017-01-04 22:52:27 +03:00
|
|
|
|
2017-01-29 06:58:28 +03:00
|
|
|
bool
|
|
|
|
ServoStyleSet::FillKeyframesForName(const nsString& aName,
|
|
|
|
const nsTimingFunction& aTimingFunction,
|
|
|
|
const ServoComputedValues* aComputedValues,
|
|
|
|
nsTArray<Keyframe>& aKeyframes)
|
|
|
|
{
|
|
|
|
NS_ConvertUTF16toUTF8 name(aName);
|
|
|
|
return Servo_StyleSet_FillKeyframesForName(mRawSet.get(),
|
|
|
|
&name,
|
|
|
|
&aTimingFunction,
|
|
|
|
aComputedValues,
|
|
|
|
&aKeyframes);
|
|
|
|
}
|
|
|
|
|
2017-03-11 04:40:47 +03:00
|
|
|
nsTArray<ComputedKeyframeValues>
|
2017-03-21 10:41:23 +03:00
|
|
|
ServoStyleSet::GetComputedKeyframeValuesFor(
|
|
|
|
const nsTArray<Keyframe>& aKeyframes,
|
|
|
|
dom::Element* aElement,
|
|
|
|
const ServoComputedValuesWithParent& aServoValues)
|
2017-03-11 04:40:47 +03:00
|
|
|
{
|
|
|
|
nsTArray<ComputedKeyframeValues> result(aKeyframes.Length());
|
|
|
|
|
|
|
|
// Construct each nsTArray<PropertyStyleAnimationValuePair> here.
|
|
|
|
result.AppendElements(aKeyframes.Length());
|
|
|
|
|
|
|
|
Servo_GetComputedKeyframeValues(&aKeyframes,
|
|
|
|
aServoValues.mCurrentStyle,
|
|
|
|
aServoValues.mParentStyle,
|
|
|
|
mRawSet.get(),
|
|
|
|
&result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-04-06 04:34:50 +03:00
|
|
|
already_AddRefed<ServoComputedValues>
|
|
|
|
ServoStyleSet::GetBaseComputedValuesForElement(Element* aElement,
|
|
|
|
nsIAtom* aPseudoTag)
|
|
|
|
{
|
|
|
|
return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
|
|
|
|
aElement,
|
|
|
|
aPseudoTag).Consume();
|
|
|
|
}
|
|
|
|
|
2017-01-04 22:52:27 +03:00
|
|
|
void
|
2017-01-15 01:34:49 +03:00
|
|
|
ServoStyleSet::RebuildData()
|
2017-01-04 22:52:27 +03:00
|
|
|
{
|
2017-03-08 08:18:39 +03:00
|
|
|
ClearNonInheritingStyleContexts();
|
2017-01-15 01:34:49 +03:00
|
|
|
Servo_StyleSet_RebuildData(mRawSet.get());
|
2017-01-04 22:52:27 +03:00
|
|
|
}
|
2017-01-04 22:52:27 +03:00
|
|
|
|
|
|
|
already_AddRefed<ServoComputedValues>
|
2017-01-06 00:12:53 +03:00
|
|
|
ServoStyleSet::ResolveServoStyle(Element* aElement)
|
2017-01-04 22:52:27 +03:00
|
|
|
{
|
2017-03-28 10:31:41 +03:00
|
|
|
return Servo_ResolveStyle(aElement, mRawSet.get(),
|
|
|
|
mAllowResolveStaleStyles).Consume();
|
2017-01-04 22:52:27 +03:00
|
|
|
}
|
2017-02-02 22:48:28 +03:00
|
|
|
|
2017-03-08 08:18:39 +03:00
|
|
|
void
|
|
|
|
ServoStyleSet::ClearNonInheritingStyleContexts()
|
|
|
|
{
|
|
|
|
for (RefPtr<nsStyleContext>& ptr : mNonInheritingStyleContexts) {
|
|
|
|
ptr = nullptr;
|
2017-03-11 04:40:47 +03:00
|
|
|
}
|
2017-03-08 08:18:39 +03:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:20:17 +03:00
|
|
|
already_AddRefed<ServoComputedValues>
|
|
|
|
ServoStyleSet::ResolveStyleLazily(Element* aElement, nsIAtom* aPseudoTag)
|
|
|
|
{
|
2017-03-08 23:20:17 +03:00
|
|
|
mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoTag);
|
|
|
|
|
2017-03-10 05:53:19 +03:00
|
|
|
MOZ_ASSERT(!sInServoTraversal);
|
|
|
|
sInServoTraversal = true;
|
|
|
|
RefPtr<ServoComputedValues> computedValues =
|
|
|
|
Servo_ResolveStyleLazily(aElement, aPseudoTag, mRawSet.get()).Consume();
|
|
|
|
|
|
|
|
if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoTag)) {
|
|
|
|
computedValues =
|
|
|
|
Servo_ResolveStyleLazily(aElement, aPseudoTag, mRawSet.get()).Consume();
|
|
|
|
}
|
|
|
|
sInServoTraversal = false;
|
|
|
|
|
|
|
|
return computedValues.forget();
|
2017-03-08 23:20:17 +03:00
|
|
|
}
|
|
|
|
|
2017-03-27 09:53:27 +03:00
|
|
|
bool
|
|
|
|
ServoStyleSet::AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
|
|
|
|
{
|
|
|
|
Servo_StyleSet_GetFontFaceRules(mRawSet.get(), &aArray);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-02-02 22:48:28 +03:00
|
|
|
bool ServoStyleSet::sInServoTraversal = false;
|