Bug 525608 part 7. Make tree pseudos use a separate hashtable instead of riding along on the rulehash. r=dbaron

This commit is contained in:
Boris Zbarsky 2009-12-11 02:37:40 -05:00
Родитель 80ebdf1890
Коммит 2f9d6df5b4
11 изменённых файлов: 156 добавлений и 220 удалений

Просмотреть файл

@ -365,14 +365,12 @@ public:
void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID, void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID,
const nsAttrValue* aClassList, const nsAttrValue* aClassList,
RuleEnumFunc aFunc, RuleProcessorData* aData); RuleEnumFunc aFunc, RuleProcessorData* aData);
void EnumerateTagRules(nsIAtom* aTag,
RuleEnumFunc aFunc, void* aData);
PLArenaPool& Arena() { return mArena; } PLArenaPool& Arena() { return mArena; }
protected: protected:
void PrependRuleToTable(PLDHashTable* aTable, const void* aKey, void PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
RuleValue* aRuleInfo); RuleValue* aRuleInfo);
void PrependRuleToTagTable(const void* aKey, RuleValue* aRuleInfo); void PrependRuleToTagTable(nsIAtom* aKey, RuleValue* aRuleInfo);
void PrependUniversalRule(RuleValue* aRuleInfo); void PrependUniversalRule(RuleValue* aRuleInfo);
// All rule values in these hashtables are arena allocated // All rule values in these hashtables are arena allocated
@ -396,15 +394,12 @@ protected:
PRUint32 mIdSelectors; PRUint32 mIdSelectors;
PRUint32 mElementsMatched; PRUint32 mElementsMatched;
PRUint32 mPseudosMatched;
PRUint32 mElementUniversalCalls; PRUint32 mElementUniversalCalls;
PRUint32 mElementNameSpaceCalls; PRUint32 mElementNameSpaceCalls;
PRUint32 mElementTagCalls; PRUint32 mElementTagCalls;
PRUint32 mElementClassCalls; PRUint32 mElementClassCalls;
PRUint32 mElementIdCalls; PRUint32 mElementIdCalls;
PRUint32 mPseudoTagCalls;
#endif // RULE_HASH_STATS #endif // RULE_HASH_STATS
}; };
@ -420,13 +415,11 @@ RuleHash::RuleHash(PRBool aQuirksMode)
mClassSelectors(0), mClassSelectors(0),
mIdSelectors(0), mIdSelectors(0),
mElementsMatched(0), mElementsMatched(0),
mPseudosMatched(0),
mElementUniversalCalls(0), mElementUniversalCalls(0),
mElementNameSpaceCalls(0), mElementNameSpaceCalls(0),
mElementTagCalls(0), mElementTagCalls(0),
mElementClassCalls(0), mElementClassCalls(0),
mElementIdCalls(0), mElementIdCalls(0)
mPseudoTagCalls(0)
#endif #endif
{ {
MOZ_COUNT_CTOR(RuleHash); MOZ_COUNT_CTOR(RuleHash);
@ -454,17 +447,14 @@ RuleHash::~RuleHash()
printf( printf(
"RuleHash(%p):\n" "RuleHash(%p):\n"
" Selectors: Universal (%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n" " Selectors: Universal (%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n"
" Content Nodes: Elements(%u) Pseudo-Elements(%u)\n" " Content Nodes: Elements(%u)\n"
" Element Calls: Universal(%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n" " Element Calls: Universal(%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n"
" Pseudo-Element Calls: Tag(%u)\n",
static_cast<void*>(this), static_cast<void*>(this),
mUniversalSelectors, mNameSpaceSelectors, mTagSelectors, mUniversalSelectors, mNameSpaceSelectors, mTagSelectors,
mClassSelectors, mIdSelectors, mClassSelectors, mIdSelectors,
mElementsMatched, mElementsMatched,
mPseudosMatched,
mElementUniversalCalls, mElementNameSpaceCalls, mElementTagCalls, mElementUniversalCalls, mElementNameSpaceCalls, mElementTagCalls,
mElementClassCalls, mElementIdCalls, mElementClassCalls, mElementIdCalls);
mPseudoTagCalls);
#ifdef PRINT_UNIVERSAL_RULES #ifdef PRINT_UNIVERSAL_RULES
{ {
RuleValue* value = mUniversalRules; RuleValue* value = mUniversalRules;
@ -511,19 +501,26 @@ void RuleHash::PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules); entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules);
} }
void RuleHash::PrependRuleToTagTable(const void* aKey, RuleValue* aRuleInfo) static void
DoPrependRuleToTagTable(PLDHashTable* aTable, nsIAtom* aKey,
RuleValue* aRuleInfo, PRInt32 aBackwardsIndex)
{ {
// Get a new or exisiting entry // Get a new or exisiting entry
RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*> RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*>
(PL_DHashTableOperate(&mTagTable, aKey, PL_DHASH_ADD)); (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
if (!entry) if (!entry)
return; return;
entry->mTag = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(aKey)); entry->mTag = aKey;
// This may give the same rule two different rule counts, but that is OK // This may give the same rule two different rule counts, but that is OK
// because we never combine two different entries in the tag table. // because we never combine two different entries in a tag table.
entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules); entry->mRules = aRuleInfo->Add(aBackwardsIndex, entry->mRules);
}
void RuleHash::PrependRuleToTagTable(nsIAtom* aKey, RuleValue* aRuleInfo)
{
DoPrependRuleToTagTable(&mTagTable, aKey, aRuleInfo, mRuleCount++);
} }
void RuleHash::PrependUniversalRule(RuleValue *aRuleInfo) void RuleHash::PrependUniversalRule(RuleValue *aRuleInfo)
@ -671,22 +668,6 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
} }
} }
void RuleHash::EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData)
{
RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
(PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP));
RULE_HASH_STAT_INCREMENT(mPseudosMatched);
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
RuleValue *tagValue = entry->mRules;
do {
RULE_HASH_STAT_INCREMENT(mPseudoTagCalls);
(*aFunc)(tagValue->mRule, tagValue->mSelector, aData);
tagValue = tagValue->mNext;
} while (tagValue);
}
}
//-------------------------------- //--------------------------------
// Attribute selectors hash table. // Attribute selectors hash table.
@ -730,12 +711,17 @@ struct RuleCascadeData {
PL_DHashTableInit(&mAnonBoxRules, &RuleHash_TagTable_Ops, nsnull, PL_DHashTableInit(&mAnonBoxRules, &RuleHash_TagTable_Ops, nsnull,
sizeof(RuleHashTagTableEntry), 16); sizeof(RuleHashTagTableEntry), 16);
memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes)); memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes));
#ifdef MOZ_XUL
PL_DHashTableInit(&mXULTreeRules, &RuleHash_TagTable_Ops, nsnull,
sizeof(RuleHashTagTableEntry), 16);
#endif
} }
~RuleCascadeData() ~RuleCascadeData()
{ {
PL_DHashTableFinish(&mAttributeSelectors); PL_DHashTableFinish(&mAttributeSelectors);
PL_DHashTableFinish(&mAnonBoxRules); PL_DHashTableFinish(&mAnonBoxRules);
PL_DHashTableFinish(&mXULTreeRules);
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mPseudoElementRuleHashes); ++i) { for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mPseudoElementRuleHashes); ++i) {
delete mPseudoElementRuleHashes[i]; delete mPseudoElementRuleHashes[i];
} }
@ -748,6 +734,9 @@ struct RuleCascadeData {
nsTArray<nsCSSSelector*> mIDSelectors; nsTArray<nsCSSSelector*> mIDSelectors;
PLDHashTable mAttributeSelectors; PLDHashTable mAttributeSelectors;
PLDHashTable mAnonBoxRules; PLDHashTable mAnonBoxRules;
#ifdef MOZ_XUL
PLDHashTable mXULTreeRules;
#endif
nsTArray<nsFontFaceRuleContainer> mFontFaceRules; nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
@ -2090,68 +2079,34 @@ nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
return NS_OK; return NS_OK;
} }
static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, #ifdef MOZ_XUL
void* aData)
{
PseudoRuleProcessorData* data = (PseudoRuleProcessorData*)aData;
if (!aSelector->IsPseudoElement())
return;
NS_ASSERTION(aSelector->mLowercaseTag == data->mPseudoTag, "RuleHash failure");
PRBool matches = PR_TRUE;
if (data->mComparator)
data->mComparator->PseudoMatches(data->mPseudoTag, aSelector, &matches);
if (matches) {
nsCSSSelector *selector = aSelector->mNext;
if (selector) { // test next selector specially
if (PRUnichar('+') == selector->mOperator) {
return; // not valid here, can't match
}
if (SelectorMatches(*data, selector, 0, PR_TRUE)) {
selector = selector->mNext;
}
else {
if (PRUnichar('>') == selector->mOperator) {
return; // immediate parent didn't match
}
}
}
if (selector &&
(! SelectorMatchesTree(*data, selector, PR_TRUE))) {
return; // remaining selectors didn't match
}
// for performance, require that every implementation of
// nsICSSStyleRule return the same pointer for nsIStyleRule (why
// would anything multiply inherit nsIStyleRule anyway?)
#ifdef DEBUG
nsCOMPtr<nsIStyleRule> iRule = do_QueryInterface(aRule);
NS_ASSERTION(static_cast<nsIStyleRule*>(aRule) == iRule.get(),
"Please fix QI so this performance optimization is valid");
#endif
data->mRuleWalker->Forward(static_cast<nsIStyleRule*>(aRule));
// nsStyleSet will deal with the !important rule
}
}
NS_IMETHODIMP NS_IMETHODIMP
nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData) nsCSSRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData)
{ {
NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT), NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
"content must be element"); "content must be element");
RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
if (cascade) { if (cascade && cascade->mXULTreeRules.entryCount) {
cascade->mRuleHash.EnumerateTagRules(aData->mPseudoTag, RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>
PseudoEnumFunc, aData); (PL_DHashTableOperate(&cascade->mXULTreeRules, aData->mPseudoTag,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
for (RuleValue *value = entry->mRules; value; value = value->mNext) {
PRBool matches = PR_TRUE;
aData->mComparator->PseudoMatches(aData->mPseudoTag, value->mSelector,
&matches);
if (matches) {
ContentEnumFunc(value->mRule, value->mSelector->mNext,
static_cast<RuleProcessorData*>(aData));
}
}
}
} }
return NS_OK; return NS_OK;
} }
#endif
inline PRBool inline PRBool
IsSiblingOperator(PRUnichar oper) IsSiblingOperator(PRUnichar oper)
@ -2407,9 +2362,9 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
} }
static PRBool static PRBool
AddRule(RuleValue* aRuleInfo, void* aCascade) AddRule(RuleValue* aRuleInfo, RuleCascadeData* aCascade)
{ {
RuleCascadeData *cascade = static_cast<RuleCascadeData*>(aCascade); RuleCascadeData * const cascade = aCascade;
// Build the rule hash. // Build the rule hash.
nsCSSPseudoElements::Type pseudoType = aRuleInfo->mSelector->PseudoType(); nsCSSPseudoElements::Type pseudoType = aRuleInfo->mSelector->PseudoType();
@ -2429,18 +2384,34 @@ AddRule(RuleValue* aRuleInfo, void* aCascade)
aRuleInfo->mSelector = aRuleInfo->mSelector->mNext; aRuleInfo->mSelector = aRuleInfo->mSelector->mNext;
ruleHash->PrependRule(aRuleInfo); ruleHash->PrependRule(aRuleInfo);
} else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) { } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*> NS_ASSERTION(!aRuleInfo->mSelector->mCasedTag &&
(PL_DHashTableOperate(&cascade->mAnonBoxRules, !aRuleInfo->mSelector->mIDList &&
aRuleInfo->mSelector->mLowercaseTag, !aRuleInfo->mSelector->mClassList &&
PL_DHASH_ADD)); !aRuleInfo->mSelector->mPseudoClassList &&
if (!entry) !aRuleInfo->mSelector->mAttrList &&
return PR_FALSE; !aRuleInfo->mSelector->mNegations &&
!aRuleInfo->mSelector->mNext &&
aRuleInfo->mSelector->mNameSpace == kNameSpaceID_Unknown,
"Parser messed up with anon box selector");
entry->mTag = aRuleInfo->mSelector->mLowercaseTag;
// Index doesn't matter here, since we'll just be walking these // Index doesn't matter here, since we'll just be walking these
// rules in order; just pass 0. // rules in order; just pass 0.
entry->mRules = aRuleInfo->Add(0, entry->mRules); DoPrependRuleToTagTable(&cascade->mAnonBoxRules,
} else { aRuleInfo->mSelector->mLowercaseTag,
aRuleInfo, 0);
}
#ifdef MOZ_XUL
else if (pseudoType == nsCSSPseudoElements::ePseudo_XULTree) {
// Index doesn't matter here, since we'll just be walking these
// rules in order; just pass 0.
DoPrependRuleToTagTable(&cascade->mXULTreeRules,
aRuleInfo->mSelector->mLowercaseTag,
aRuleInfo, 0);
}
#endif
else {
NS_ASSERTION(pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
"Unexpected pseudoType");
cascade->mRuleHash.PrependRule(aRuleInfo); cascade->mRuleHash.PrependRule(aRuleInfo);
} }

Просмотреть файл

@ -95,7 +95,9 @@ public:
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData); NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); #ifdef MOZ_XUL
NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
#endif
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
nsReStyleHint* aResult); nsReStyleHint* aResult);

Просмотреть файл

@ -93,7 +93,9 @@ public:
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData); NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); #ifdef MOZ_XUL
NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
#endif
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
nsReStyleHint* aResult); nsReStyleHint* aResult);
@ -170,11 +172,13 @@ HTMLCSSStyleSheetImpl::RulesMatching(AnonBoxRuleProcessorData* aData)
return NS_OK; return NS_OK;
} }
#ifdef MOZ_XUL
NS_IMETHODIMP NS_IMETHODIMP
HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData) HTMLCSSStyleSheetImpl::RulesMatching(XULTreeRuleProcessorData* aData)
{ {
return NS_OK; return NS_OK;
} }
#endif
NS_IMETHODIMP NS_IMETHODIMP
HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument)

Просмотреть файл

@ -581,12 +581,13 @@ nsHTMLStyleSheet::RulesMatching(AnonBoxRuleProcessorData* aData)
return NS_OK; return NS_OK;
} }
#ifdef MOZ_XUL
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData) nsHTMLStyleSheet::RulesMatching(XULTreeRuleProcessorData* aData)
{ {
return NS_OK; return NS_OK;
} }
#endif
// nsIStyleSheet api // nsIStyleSheet api
NS_IMETHODIMP NS_IMETHODIMP

Просмотреть файл

@ -81,7 +81,9 @@ public:
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData); NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); #ifdef MOZ_XUL
NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
#endif
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
nsReStyleHint* aResult); nsReStyleHint* aResult);
virtual nsReStyleHint virtual nsReStyleHint

Просмотреть файл

@ -53,15 +53,18 @@ struct RuleProcessorData;
struct ElementRuleProcessorData; struct ElementRuleProcessorData;
struct PseudoElementRuleProcessorData; struct PseudoElementRuleProcessorData;
struct AnonBoxRuleProcessorData; struct AnonBoxRuleProcessorData;
struct PseudoRuleProcessorData; #ifdef MOZ_XUL
struct XULTreeRuleProcessorData;
#endif
struct StateRuleProcessorData; struct StateRuleProcessorData;
struct AttributeRuleProcessorData; struct AttributeRuleProcessorData;
class nsPresContext; class nsPresContext;
// IID for the nsIStyleRuleProcessor interface {a4ec760e-6bfb-4b9f-bd08-9d1c23b700f6} // IID for the nsIStyleRuleProcessor interface
// {ec92bc0c-9518-48ea-9289-74e654659be9}
#define NS_ISTYLE_RULE_PROCESSOR_IID \ #define NS_ISTYLE_RULE_PROCESSOR_IID \
{ 0xa4ec760e, 0x6bfb, 0x4b9f, \ { 0xec92bc0c, 0x9518, 0x48ea, \
{ 0xbd, 0x08, 0x9d, 0x1c, 0x23, 0xb7, 0x00, 0xf6 } } { 0x92, 0x89, 0x74, 0xe6, 0x54, 0x65, 0x9b, 0xe9 } }
/* The style rule processor interface is a mechanism to separate the matching /* The style rule processor interface is a mechanism to separate the matching
* of style rules from style sheet instances. * of style rules from style sheet instances.
@ -98,11 +101,13 @@ public:
*/ */
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData) = 0; NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData) = 0;
#ifdef MOZ_XUL
/** /**
* Just like the previous |RulesMatching|, except for a given content * Just like the previous |RulesMatching|, except for a given content
* node <em>and pseudo</em>. * node <em>and tree pseudo</em>.
*/ */
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0; NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData) = 0;
#endif
/** /**
* Return how (as described by nsReStyleHint) style can depend on a * Return how (as described by nsReStyleHint) style can depend on a

Просмотреть файл

@ -211,24 +211,27 @@ struct AnonBoxRuleProcessorData {
nsRuleWalker* mRuleWalker; nsRuleWalker* mRuleWalker;
}; };
struct PseudoRuleProcessorData : public RuleProcessorData { #ifdef MOZ_XUL
PseudoRuleProcessorData(nsPresContext* aPresContext, struct XULTreeRuleProcessorData : public RuleProcessorData {
nsIContent* aParentContent, XULTreeRuleProcessorData(nsPresContext* aPresContext,
nsIAtom* aPseudoTag, nsIContent* aParentContent,
nsICSSPseudoComparator* aComparator, nsRuleWalker* aRuleWalker,
nsRuleWalker* aRuleWalker) nsIAtom* aPseudoTag,
: RuleProcessorData(aPresContext, aParentContent, aRuleWalker) nsICSSPseudoComparator* aComparator)
: RuleProcessorData(aPresContext, aParentContent, aRuleWalker),
mPseudoTag(aPseudoTag),
mComparator(aComparator)
{ {
NS_PRECONDITION(aPresContext, "null pointer"); NS_PRECONDITION(aPresContext, "null pointer");
NS_PRECONDITION(aPseudoTag, "null pointer"); NS_PRECONDITION(aPseudoTag, "null pointer");
NS_PRECONDITION(aRuleWalker, "null pointer"); NS_PRECONDITION(aRuleWalker, "null pointer");
mPseudoTag = aPseudoTag; NS_PRECONDITION(aComparator, "must have a comparator");
mComparator = aComparator;
} }
nsIAtom* mPseudoTag; nsIAtom* mPseudoTag;
nsICSSPseudoComparator* mComparator; nsICSSPseudoComparator* mComparator;
}; };
#endif
struct StateRuleProcessorData : public RuleProcessorData { struct StateRuleProcessorData : public RuleProcessorData {
StateRuleProcessorData(nsPresContext* aPresContext, StateRuleProcessorData(nsPresContext* aPresContext,

Просмотреть файл

@ -411,12 +411,11 @@ nsStyleSet::EnableQuirkStyleSheet(PRBool aEnable)
#endif #endif
} }
template<class T>
static PRBool static PRBool
EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
{ {
ElementRuleProcessorData* data = T* data = static_cast<T*>(aData);
static_cast<ElementRuleProcessorData*>(aData);
aProcessor->RulesMatching(data); aProcessor->RulesMatching(data);
return PR_TRUE; return PR_TRUE;
} }
@ -748,7 +747,8 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent,
if (aContent && presContext) { if (aContent && presContext) {
nsRuleWalker ruleWalker(mRuleTree); nsRuleWalker ruleWalker(mRuleTree);
ElementRuleProcessorData data(presContext, aContent, &ruleWalker); ElementRuleProcessorData data(presContext, aContent, &ruleWalker);
FileRules(EnumRulesMatching, &data, aContent, &ruleWalker); FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aContent,
&ruleWalker);
result = GetContext(presContext, aParentContext, result = GetContext(presContext, aParentContext,
ruleWalker.GetCurrentNode(), nsnull, ruleWalker.GetCurrentNode(), nsnull,
nsCSSPseudoElements::ePseudo_NotPseudoElement).get(); nsCSSPseudoElements::ePseudo_NotPseudoElement).get();
@ -812,65 +812,6 @@ nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType,
aRuleWalker->Forward(mFirstLineRule); aRuleWalker->Forward(mFirstLineRule);
} }
static PRBool
EnumPseudoRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
{
PseudoRuleProcessorData* data =
static_cast<PseudoRuleProcessorData*>(aData);
aProcessor->RulesMatching(data);
return PR_TRUE;
}
already_AddRefed<nsStyleContext>
nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent,
nsIAtom* aPseudoTag,
nsCSSPseudoElements::Type aPseudoType,
nsStyleContext* aParentContext,
nsICSSPseudoComparator* aComparator)
{
NS_ENSURE_FALSE(mInShutdown, nsnull);
nsStyleContext* result = nsnull;
nsPresContext *presContext = PresContext();
NS_ASSERTION(aPseudoTag, "must have pseudo tag");
NS_ASSERTION(!aParentContent ||
aParentContent->IsNodeOfType(nsINode::eELEMENT),
"content (if non-null) must be element");
NS_ASSERTION(aParentContent ||
nsCSSAnonBoxes::IsAnonBox(aPseudoTag),
"null content must correspond to anonymous box");
NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) ||
nsCSSPseudoElements::IsPseudoElement(aPseudoTag),
"aPseudoTag must be pseudo-element or anonymous box");
NS_ASSERTION(nsCSSPseudoElements::GetPseudoType(aPseudoTag) == aPseudoType,
"Incorrect pseudo type");
if (aPseudoTag && presContext) {
nsRuleWalker ruleWalker(mRuleTree);
PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
aComparator, &ruleWalker);
FileRules(EnumPseudoRulesMatching, &data, aParentContent, &ruleWalker);
result = GetContext(presContext, aParentContext,
ruleWalker.GetCurrentNode(), aPseudoTag,
aPseudoType).get();
}
return result;
}
static PRBool
EnumPseudoElementRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
{
PseudoElementRuleProcessorData* data =
static_cast<PseudoElementRuleProcessorData*>(aData);
aProcessor->RulesMatching(data);
return PR_TRUE;
}
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent, nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent,
nsCSSPseudoElements::Type aType, nsCSSPseudoElements::Type aType,
@ -889,7 +830,8 @@ nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent,
PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker, PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker,
aType); aType);
WalkRestrictionRule(aType, &ruleWalker); WalkRestrictionRule(aType, &ruleWalker);
FileRules(EnumPseudoElementRulesMatching, &data, aParentContent, &ruleWalker); FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
aParentContent, &ruleWalker);
return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(), return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
nsCSSPseudoElements::GetPseudoAtom(aType), aType); nsCSSPseudoElements::GetPseudoAtom(aType), aType);
@ -918,7 +860,8 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
WalkRestrictionRule(aType, &ruleWalker); WalkRestrictionRule(aType, &ruleWalker);
// not the root if there was a restriction rule // not the root if there was a restriction rule
nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode(); nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
FileRules(EnumPseudoElementRulesMatching, &data, aParentContent, &ruleWalker); FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
aParentContent, &ruleWalker);
nsRuleNode *ruleNode = ruleWalker.GetCurrentNode(); nsRuleNode *ruleNode = ruleWalker.GetCurrentNode();
if (ruleNode == adjustedRoot) { if (ruleNode == adjustedRoot) {
@ -946,16 +889,6 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
return result.forget(); return result.forget();
} }
static PRBool
EnumAnonBoxRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
{
AnonBoxRuleProcessorData* data =
static_cast<AnonBoxRuleProcessorData*>(aData);
aProcessor->RulesMatching(data);
return PR_TRUE;
}
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
nsStyleContext* aParentContext) nsStyleContext* aParentContext)
@ -974,12 +907,41 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
nsRuleWalker ruleWalker(mRuleTree); nsRuleWalker ruleWalker(mRuleTree);
nsPresContext *presContext = PresContext(); nsPresContext *presContext = PresContext();
AnonBoxRuleProcessorData data(presContext, aPseudoTag, &ruleWalker); AnonBoxRuleProcessorData data(presContext, aPseudoTag, &ruleWalker);
FileRules(EnumAnonBoxRulesMatching, &data, nsnull, &ruleWalker); FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nsnull,
&ruleWalker);
return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(), return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox); aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox);
} }
#ifdef MOZ_XUL
already_AddRefed<nsStyleContext>
nsStyleSet::ResolveXULTreePseudoStyle(nsIContent* aParentContent,
nsIAtom* aPseudoTag,
nsStyleContext* aParentContext,
nsICSSPseudoComparator* aComparator)
{
NS_ENSURE_FALSE(mInShutdown, nsnull);
NS_ASSERTION(aPseudoTag, "must have pseudo tag");
NS_ASSERTION(aParentContent->IsNodeOfType(nsINode::eELEMENT),
"content (if non-null) must be element");
NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag),
"Unexpected pseudo");
nsRuleWalker ruleWalker(mRuleTree);
nsPresContext *presContext = PresContext();
XULTreeRuleProcessorData data(presContext, aParentContent, &ruleWalker,
aPseudoTag, aComparator);
FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data, aParentContent,
&ruleWalker);
return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree);
}
#endif
PRBool PRBool
nsStyleSet::AppendFontFaceRules(nsPresContext* aPresContext, nsStyleSet::AppendFontFaceRules(nsPresContext* aPresContext,
nsTArray<nsFontFaceRuleContainer>& aArray) nsTArray<nsFontFaceRuleContainer>& aArray)

Просмотреть файл

@ -150,27 +150,9 @@ class nsStyleSet
ResolveXULTreePseudoStyle(nsIContent* aParentContent, ResolveXULTreePseudoStyle(nsIContent* aParentContent,
nsIAtom* aPseudoTag, nsIAtom* aPseudoTag,
nsStyleContext* aParentContext, nsStyleContext* aParentContext,
nsICSSPseudoComparator* aComparator) { nsICSSPseudoComparator* aComparator);
NS_PRECONDITION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag),
"Unexpected pseudo");
return ResolvePseudoStyleFor(aParentContent, aPseudoTag,
nsCSSPseudoElements::ePseudo_XULTree,
aParentContext, aComparator);
}
#endif #endif
private:
// get a style context for a pseudo-element (i.e.,
// |aPseudoTag == nsCOMPtr<nsIAtom>(do_GetAtom(":first-line"))|, in
// which case aParentContent must be non-null, or an anonymous box, in
// which case it may be null or non-null.
already_AddRefed<nsStyleContext>
ResolvePseudoStyleFor(nsIContent* aParentContent,
nsIAtom* aPseudoTag,
nsCSSPseudoElements::Type aPseudoType,
nsStyleContext* aParentContext,
nsICSSPseudoComparator* aComparator = nsnull);
public:
// Append all the currently-active font face rules to aArray. Return // Append all the currently-active font face rules to aArray. Return
// true for success and false for failure. // true for success and false for failure.
PRBool AppendFontFaceRules(nsPresContext* aPresContext, PRBool AppendFontFaceRules(nsPresContext* aPresContext,

Просмотреть файл

@ -767,11 +767,13 @@ nsTransitionManager::RulesMatching(AnonBoxRuleProcessorData* aData)
return NS_OK; return NS_OK;
} }
#ifdef MOZ_XUL
NS_IMETHODIMP NS_IMETHODIMP
nsTransitionManager::RulesMatching(PseudoRuleProcessorData* aData) nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData)
{ {
return NS_OK; return NS_OK;
} }
#endif
NS_IMETHODIMP NS_IMETHODIMP
nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData, nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData,

Просмотреть файл

@ -88,7 +88,9 @@ public:
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData); NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); #ifdef MOZ_XUL
NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
#endif
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
nsReStyleHint* aResult); nsReStyleHint* aResult);
virtual nsReStyleHint virtual nsReStyleHint