Skip to content

Commit

Permalink
Bug 1367923 - Store Servo decls when link preshints change. r=Manishe…
Browse files Browse the repository at this point in the history
…arth

When any of the link preshints (link, vlink, alink) on <body> are set, we store
a Servo declaration block to hold the color from the hint.

This uses a one-off approach instead of `nsMappedAttributes` that is used for
other preshints because it depends on element state and also it affects links
through the document (as opposed to the element where the attribute is set).

MozReview-Commit-ID: KUvyCq9KfHT
  • Loading branch information
jryans committed Jun 2, 2017
1 parent 562a57b commit f60ca23
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 25 deletions.
53 changes: 44 additions & 9 deletions layout/style/ServoBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "nsIPrincipal.h"
#include "nsIURI.h"
#include "nsFontMetrics.h"
#include "nsHTMLStyleSheet.h"
#include "nsMappedAttributes.h"
#include "nsMediaFeatures.h"
#include "nsNameSpaceManager.h"
Expand Down Expand Up @@ -448,12 +449,18 @@ Gecko_GetSMILOverrideDeclarationBlock(RawGeckoElementBorrowed aElement)
return decl->AsServo()->RefRawStrong();
}

RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
const RawServoDeclarationBlockStrong*
AsRefRawStrong(const RefPtr<RawServoDeclarationBlock>& aDecl)
{
static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
sizeof(RawServoDeclarationBlockStrong),
"RefPtr should just be a pointer");
return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&aDecl);
}

RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
{
const nsMappedAttributes* attrs = aElement->GetMappedAttributes();
if (!attrs) {
auto* svg = nsSVGElement::FromContentOrNull(aElement);
Expand All @@ -465,27 +472,55 @@ Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
return nullptr;
}

const RefPtr<RawServoDeclarationBlock>& servo = attrs->GetServoStyle();
return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&servo);
return AsRefRawStrong(attrs->GetServoStyle());
}

RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetExtraContentStyleDeclarations(RawGeckoElementBorrowed aElement)
{
static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
sizeof(RawServoDeclarationBlockStrong),
"RefPtr should just be a pointer");
if (!aElement->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
return nullptr;
}
const HTMLTableCellElement* cell = static_cast<const HTMLTableCellElement*>(aElement);
if (nsMappedAttributes* attrs = cell->GetMappedAttributesInheritedFromTable()) {
const RefPtr<RawServoDeclarationBlock>& servo = attrs->GetServoStyle();
return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&servo);
return AsRefRawStrong(attrs->GetServoStyle());
}
return nullptr;
}

RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetUnvisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
{
nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
if (!sheet) {
return nullptr;
}

return AsRefRawStrong(sheet->GetServoUnvisitedLinkDecl());
}

RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetVisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
{
nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
if (!sheet) {
return nullptr;
}

return AsRefRawStrong(sheet->GetServoVisitedLinkDecl());
}

RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetActiveLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
{
nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
if (!sheet) {
return nullptr;
}

return AsRefRawStrong(sheet->GetServoActiveLinkDecl());
}

static nsIAtom*
PseudoTagAndCorrectElementForAnimation(const Element*& aElementOrPseudo) {
if (aElementOrPseudo->IsGeneratedContentContainerForBefore()) {
Expand Down
6 changes: 6 additions & 0 deletions layout/style/ServoBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed element);
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetExtraContentStyleDeclarations(RawGeckoElementBorrowed element);
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetUnvisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed element);
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetVisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed element);
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetActiveLinkAttrDeclarationBlock(RawGeckoElementBorrowed element);

// Animations
bool
Expand Down
50 changes: 35 additions & 15 deletions layout/style/nsHTMLStyleSheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 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/.
*
* This Original Code has been modified by IBM Corporation. Modifications made by IBM
* This Original Code has been modified by IBM Corporation. Modifications made by IBM
* described herein are Copyright (c) International Business Machines Corporation, 2000.
* Modifications to Mozilla code or documentation identified per MPL Section 3.3
*
Expand Down Expand Up @@ -36,6 +36,7 @@
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/RestyleManager.h"
#include "mozilla/RestyleManagerInlines.h"
#include "mozilla/ServoStyleSet.h"

using namespace mozilla;
using namespace mozilla::dom;
Expand Down Expand Up @@ -476,51 +477,70 @@ nsHTMLStyleSheet::Reset()
mVisitedRule = nullptr;
mActiveRule = nullptr;

mServoUnvisitedLinkDecl = nullptr;
mServoVisitedLinkDecl = nullptr;
mServoActiveLinkDecl = nullptr;

mLangRuleTable.Clear();
mMappedAttrTable.Clear();
mMappedAttrsDirty = false;
}

nsresult
nsHTMLStyleSheet::ImplLinkColorSetter(RefPtr<HTMLColorRule>& aRule, nscolor aColor)
nsHTMLStyleSheet::ImplLinkColorSetter(
RefPtr<HTMLColorRule>& aRule,
RefPtr<RawServoDeclarationBlock>& aDecl,
nscolor aColor)
{
if (aRule && aRule->mColor == aColor) {
if (!mDocument || !mDocument->GetShell()) {
return NS_OK;
}

aRule = new HTMLColorRule(aColor);
if (!aRule)
return NS_ERROR_OUT_OF_MEMORY;
RestyleManager* restyle =
mDocument->GetShell()->GetPresContext()->RestyleManager();

if (restyle->IsServo()) {
MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
aDecl = Servo_DeclarationBlock_CreateEmpty().Consume();
Servo_DeclarationBlock_SetColorValue(aDecl.get(), eCSSProperty_color,
aColor);
} else {
if (aRule && aRule->mColor == aColor) {
return NS_OK;
}

aRule = new HTMLColorRule(aColor);
if (!aRule) {
return NS_ERROR_OUT_OF_MEMORY;
}
}

// Now make sure we restyle any links that might need it. This
// shouldn't happen often, so just rebuilding everything is ok.
if (mDocument && mDocument->GetShell()) {
Element* root = mDocument->GetRootElement();
if (root) {
mDocument->GetShell()->GetPresContext()->RestyleManager()->
PostRestyleEvent(root, eRestyle_Subtree, nsChangeHint(0));
}
Element* root = mDocument->GetRootElement();
if (root) {
restyle->PostRestyleEvent(root, eRestyle_Subtree, nsChangeHint(0));
}
return NS_OK;
}

nsresult
nsHTMLStyleSheet::SetLinkColor(nscolor aColor)
{
return ImplLinkColorSetter(mLinkRule, aColor);
return ImplLinkColorSetter(mLinkRule, mServoUnvisitedLinkDecl, aColor);
}


nsresult
nsHTMLStyleSheet::SetActiveLinkColor(nscolor aColor)
{
return ImplLinkColorSetter(mActiveRule, aColor);
return ImplLinkColorSetter(mActiveRule, mServoActiveLinkDecl, aColor);
}

nsresult
nsHTMLStyleSheet::SetVisitedLinkColor(nscolor aColor)
{
return ImplLinkColorSetter(mVisitedRule, aColor);
return ImplLinkColorSetter(mVisitedRule, mServoVisitedLinkDecl, aColor);
}

already_AddRefed<nsMappedAttributes>
Expand Down
18 changes: 17 additions & 1 deletion layout/style/nsHTMLStyleSheet.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

class nsIDocument;
class nsMappedAttributes;
struct RawServoDeclarationBlock;

class nsHTMLStyleSheet final : public nsIStyleRuleProcessor
{
Expand Down Expand Up @@ -58,6 +59,16 @@ class nsHTMLStyleSheet final : public nsIStyleRuleProcessor
nsresult SetActiveLinkColor(nscolor aColor);
nsresult SetVisitedLinkColor(nscolor aColor);

const RefPtr<RawServoDeclarationBlock>& GetServoUnvisitedLinkDecl() const {
return mServoUnvisitedLinkDecl;
}
const RefPtr<RawServoDeclarationBlock>& GetServoVisitedLinkDecl() const {
return mServoVisitedLinkDecl;
}
const RefPtr<RawServoDeclarationBlock>& GetServoActiveLinkDecl() const {
return mServoActiveLinkDecl;
}

// Mapped Attribute management methods
already_AddRefed<nsMappedAttributes>
UniqueMappedAttributes(nsMappedAttributes* aMapped);
Expand Down Expand Up @@ -100,7 +111,9 @@ class nsHTMLStyleSheet final : public nsIStyleRuleProcessor
};

// Implementation of SetLink/VisitedLink/ActiveLinkColor
nsresult ImplLinkColorSetter(RefPtr<HTMLColorRule>& aRule, nscolor aColor);
nsresult ImplLinkColorSetter(RefPtr<HTMLColorRule>& aRule,
RefPtr<RawServoDeclarationBlock>& aDecl,
nscolor aColor);

class GenericTableRule;
friend class GenericTableRule;
Expand Down Expand Up @@ -177,6 +190,9 @@ class nsHTMLStyleSheet final : public nsIStyleRuleProcessor
RefPtr<HTMLColorRule> mLinkRule;
RefPtr<HTMLColorRule> mVisitedRule;
RefPtr<HTMLColorRule> mActiveRule;
RefPtr<RawServoDeclarationBlock> mServoUnvisitedLinkDecl;
RefPtr<RawServoDeclarationBlock> mServoVisitedLinkDecl;
RefPtr<RawServoDeclarationBlock> mServoActiveLinkDecl;
RefPtr<TableQuirkColorRule> mTableQuirkColorRule;
RefPtr<TableTHRule> mTableTHRule;

Expand Down

0 comments on commit f60ca23

Please sign in to comment.