From d1916dab075e8faccb160c2aa2a93af32779db1f Mon Sep 17 00:00:00 2001 From: "peterl%netscape.com" Date: Fri, 8 Oct 1999 03:09:31 +0000 Subject: [PATCH] First step at fixing 12106, factored out style rule processing from style sheets into a seperate style rule processor interface r=troy git-svn-id: svn://10.0.0.236/trunk@50193 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/public/nsIStyleRuleProcessor.h | 68 ++++ mozilla/content/base/public/nsIStyleSheet.h | 20 +- mozilla/content/base/src/nsStyleSet.cpp | 369 ++++++++++-------- .../html/style/public/nsICSSStyleSheet.h | 3 + .../html/style/src/nsCSSStyleSheet.cpp | 114 +++--- .../html/style/src/nsHTMLCSSStyleSheet.cpp | 84 ++-- .../html/style/src/nsHTMLStyleSheet.cpp | 118 +++--- .../html/style/src/nsICSSStyleRuleProcessor.h | 49 +++ mozilla/layout/base/public/MANIFEST | 1 + mozilla/layout/base/public/Makefile.in | 1 + mozilla/layout/base/public/makefile.win | 1 + .../base/public/nsIStyleRuleProcessor.h | 68 ++++ mozilla/layout/base/public/nsIStyleSheet.h | 20 +- mozilla/layout/base/src/nsStyleSet.cpp | 369 ++++++++++-------- .../html/style/public/nsICSSStyleSheet.h | 3 + mozilla/layout/html/style/src/MANIFEST | 1 + mozilla/layout/html/style/src/Makefile.in | 1 + mozilla/layout/html/style/src/makefile.win | 1 + .../layout/html/style/src/nsCSSStyleSheet.cpp | 114 +++--- .../html/style/src/nsHTMLCSSStyleSheet.cpp | 84 ++-- .../html/style/src/nsHTMLStyleSheet.cpp | 118 +++--- .../html/style/src/nsICSSStyleRuleProcessor.h | 49 +++ mozilla/layout/style/nsCSSStyleSheet.cpp | 114 +++--- mozilla/layout/style/nsHTMLCSSStyleSheet.cpp | 84 ++-- mozilla/layout/style/nsHTMLStyleSheet.cpp | 118 +++--- mozilla/layout/style/nsICSSStyleSheet.h | 3 + mozilla/layout/style/nsIStyleRuleProcessor.h | 68 ++++ mozilla/layout/style/nsIStyleSheet.h | 20 +- mozilla/layout/style/nsStyleSet.cpp | 369 ++++++++++-------- 29 files changed, 1514 insertions(+), 918 deletions(-) create mode 100644 mozilla/content/base/public/nsIStyleRuleProcessor.h create mode 100644 mozilla/content/html/style/src/nsICSSStyleRuleProcessor.h create mode 100644 mozilla/layout/base/public/nsIStyleRuleProcessor.h create mode 100644 mozilla/layout/html/style/src/nsICSSStyleRuleProcessor.h create mode 100644 mozilla/layout/style/nsIStyleRuleProcessor.h diff --git a/mozilla/content/base/public/nsIStyleRuleProcessor.h b/mozilla/content/base/public/nsIStyleRuleProcessor.h new file mode 100644 index 00000000000..ff317a9445a --- /dev/null +++ b/mozilla/content/base/public/nsIStyleRuleProcessor.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsIStyleRuleProcessor_h___ +#define nsIStyleRuleProcessor_h___ + +#include + +#include "nslayout.h" +#include "nsISupports.h" + +class nsIStyleSheet; +class nsIStyleContext; +class nsIPresContext; +class nsIContent; +class nsISupportsArray; +class nsIAtom; + +// IID for the nsIStyleRuleProcessor interface {015575fe-7b6c-11d3-ba05-001083023c2b} +#define NS_ISTYLE_RULE_PROCESSOR_IID \ +{0x015575fe, 0x7b6c, 0x11d3, {0xba, 0x05, 0x00, 0x10, 0x83, 0x02, 0x3c, 0x2b}} + +/* The style rule processor interface is a mechanism to seperate the matching + * of style rules from style sheet instances. + * Simple style sheets can and will act as their own processor. + * Sheets where rule ordering interlaces between multiple sheets, will need to + * share a single rule processor between them (CSS sheets do this for cascading order) + */ +class nsIStyleRuleProcessor : public nsISupports { +public: + static const nsIID& GetIID() { static nsIID iid = NS_ISTYLE_RULE_PROCESSOR_IID; return iid; } + + // populate supports array with nsIStyleRule* + // rules are ordered, those with higher precedence come last + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) = 0; + + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) = 0; + + // Test if style is dependent on content state + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent) = 0; +}; + +#endif /* nsIStyleRuleProcessor_h___ */ diff --git a/mozilla/content/base/public/nsIStyleSheet.h b/mozilla/content/base/public/nsIStyleSheet.h index 1a630e76698..dcbf8be9305 100644 --- a/mozilla/content/base/public/nsIStyleSheet.h +++ b/mozilla/content/base/public/nsIStyleSheet.h @@ -29,6 +29,7 @@ class nsIPresContext; class nsIContent; class nsIDocument; class nsIStyleContext; +class nsIStyleRuleProcessor; // IID for the nsIStyleSheet interface {8c4a80a0-ad6a-11d1-8031-006008159b5a} #define NS_ISTYLE_SHEET_IID \ @@ -54,22 +55,9 @@ public: NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const = 0; // may be null NS_IMETHOD SetOwningDocument(nsIDocument* aDocument) = 0; - // populate supports array with nsIStyleRule* - // rules are ordered, those with higher precedence come last - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) = 0; - - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) = 0; - - // Test if style is dependent on content state - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent) = 0; + // style rule processor access + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor) = 0; // XXX style rule enumerations diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index 0fa87d6d040..69a94c90558 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -18,6 +18,7 @@ #include "nsCOMPtr.h" #include "nsIStyleSet.h" #include "nsIStyleSheet.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleRule.h" #include "nsIStyleContext.h" #include "nsISupportsArray.h" @@ -174,15 +175,22 @@ private: protected: virtual ~StyleSetImpl(); PRBool EnsureArray(nsISupportsArray** aArray); + void RecycleArray(nsISupportsArray** aArray); + void ClearRuleProcessors(void); + nsresult GatherRuleProcessors(void); + nsIStyleContext* GetContext(nsIPresContext* aPresContext, nsIStyleContext* aParentContext, nsIAtom* aPseudoTag, nsISupportsArray* aRules, PRBool aForceUnique, PRBool& aUsedRules); void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets); void ListContexts(nsIStyleContext* aRootContext, FILE* out, PRInt32 aIndent); - nsISupportsArray* mOverrideSheets; - nsISupportsArray* mDocSheets; - nsISupportsArray* mBackstopSheets; + nsISupportsArray* mOverrideSheets; // most significant first + nsISupportsArray* mDocSheets; // " " + nsISupportsArray* mBackstopSheets; // " " + + nsISupportsArray* mRuleProcessors; // least significant first + nsISupportsArray* mRecycler; nsIStyleFrameConstruction* mFrameConstructor; @@ -198,6 +206,7 @@ StyleSetImpl::StyleSetImpl() : mOverrideSheets(nsnull), mDocSheets(nsnull), mBackstopSheets(nsnull), + mRuleProcessors(nsnull), mRecycler(nsnull), mFrameConstructor(nsnull) { @@ -211,6 +220,7 @@ StyleSetImpl::~StyleSetImpl() NS_IF_RELEASE(mOverrideSheets); NS_IF_RELEASE(mDocSheets); NS_IF_RELEASE(mBackstopSheets); + NS_IF_RELEASE(mRuleProcessors); NS_IF_RELEASE(mFrameConstructor); NS_IF_RELEASE(mRecycler); } @@ -224,13 +234,94 @@ NS_IMPL_ISUPPORTS2(StyleSetImpl, nsIStyleSet, nsITimeRecorder) PRBool StyleSetImpl::EnsureArray(nsISupportsArray** aArray) { if (nsnull == *aArray) { - if (NS_OK != NS_NewISupportsArray(aArray)) { - return PR_FALSE; + (*aArray) = mRecycler; + mRecycler = nsnull; + if (nsnull == *aArray) { + if (NS_OK != NS_NewISupportsArray(aArray)) { + return PR_FALSE; + } } } return PR_TRUE; } +void +StyleSetImpl::RecycleArray(nsISupportsArray** aArray) +{ + if (! mRecycler) { + mRecycler = *aArray; // take ref + mRecycler->Clear(); + *aArray = nsnull; + } + else { // already have a recycled array + NS_RELEASE(*aArray); + } +} + +void +StyleSetImpl::ClearRuleProcessors(void) +{ + if (mRuleProcessors) { + RecycleArray(&mRuleProcessors); + } +} + +struct RuleProcessorData { + RuleProcessorData(nsISupportsArray* aRuleProcessors) + : mRuleProcessors(aRuleProcessors), + mPrevProcessor(nsnull) + {} + + nsISupportsArray* mRuleProcessors; + nsIStyleRuleProcessor* mPrevProcessor; +}; + +static PRBool +EnumRuleProcessor(nsISupports* aSheet, void* aData) +{ + nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + RuleProcessorData* data = (RuleProcessorData*)aData; + + nsIStyleRuleProcessor* processor = nsnull; + nsresult result = sheet->GetStyleRuleProcessor(processor, data->mPrevProcessor); + if (NS_SUCCEEDED(result) && processor) { + if (processor != data->mPrevProcessor) { + data->mRuleProcessors->AppendElement(processor); + data->mPrevProcessor = processor; // ref is held by array + } + NS_RELEASE(processor); + } + return PR_TRUE; +} + +nsresult +StyleSetImpl::GatherRuleProcessors(void) +{ + nsresult result = NS_ERROR_OUT_OF_MEMORY; + if (EnsureArray(&mRuleProcessors)) { + RuleProcessorData data(mRuleProcessors); + if (mBackstopSheets) { + mBackstopSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + if (mDocSheets) { + data.mPrevProcessor = nsnull; + mDocSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + if (mOverrideSheets) { + data.mPrevProcessor = nsnull; + mOverrideSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + result = NS_OK; + PRUint32 count; + mRuleProcessors->Count(&count); + if (0 == count) { + RecycleArray(&mRuleProcessors); + } + } + return result; +} + + // ----- Override sheets void StyleSetImpl::AppendOverrideStyleSheet(nsIStyleSheet* aSheet) @@ -239,6 +330,7 @@ void StyleSetImpl::AppendOverrideStyleSheet(nsIStyleSheet* aSheet) if (EnsureArray(&mOverrideSheets)) { mOverrideSheets->RemoveElement(aSheet); mOverrideSheets->AppendElement(aSheet); + ClearRuleProcessors(); } } @@ -250,6 +342,7 @@ void StyleSetImpl::InsertOverrideStyleSheetAfter(nsIStyleSheet* aSheet, mOverrideSheets->RemoveElement(aSheet); PRInt32 index = mOverrideSheets->IndexOf(aAfterSheet); mOverrideSheets->InsertElementAt(aSheet, ++index); + ClearRuleProcessors(); } } @@ -261,6 +354,7 @@ void StyleSetImpl::InsertOverrideStyleSheetBefore(nsIStyleSheet* aSheet, mOverrideSheets->RemoveElement(aSheet); PRInt32 index = mOverrideSheets->IndexOf(aBeforeSheet); mOverrideSheets->InsertElementAt(aSheet, ((-1 < index) ? index : 0)); + ClearRuleProcessors(); } } @@ -270,6 +364,7 @@ void StyleSetImpl::RemoveOverrideStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mOverrideSheets) { mOverrideSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -325,6 +420,7 @@ void StyleSetImpl::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocumen if (nsnull == mFrameConstructor) { aSheet->QueryInterface(kIStyleFrameConstructionIID, (void **)&mFrameConstructor); } + ClearRuleProcessors(); } } @@ -334,6 +430,7 @@ void StyleSetImpl::RemoveDocStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mDocSheets) { mDocSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -365,6 +462,7 @@ void StyleSetImpl::AppendBackstopStyleSheet(nsIStyleSheet* aSheet) if (EnsureArray(&mBackstopSheets)) { mBackstopSheets->RemoveElement(aSheet); mBackstopSheets->AppendElement(aSheet); + ClearRuleProcessors(); } } @@ -376,6 +474,7 @@ void StyleSetImpl::InsertBackstopStyleSheetAfter(nsIStyleSheet* aSheet, mBackstopSheets->RemoveElement(aSheet); PRInt32 index = mBackstopSheets->IndexOf(aAfterSheet); mBackstopSheets->InsertElementAt(aSheet, ++index); + ClearRuleProcessors(); } } @@ -387,6 +486,7 @@ void StyleSetImpl::InsertBackstopStyleSheetBefore(nsIStyleSheet* aSheet, mBackstopSheets->RemoveElement(aSheet); PRInt32 index = mBackstopSheets->IndexOf(aBeforeSheet); mBackstopSheets->InsertElementAt(aSheet, ((-1 < index) ? index : 0)); + ClearRuleProcessors(); } } @@ -396,6 +496,7 @@ void StyleSetImpl::RemoveBackstopStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mBackstopSheets) { mBackstopSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -429,8 +530,7 @@ struct RulesMatchingData { mMedium(aMedium), mContent(aContent), mParentContext(aParentContext), - mResults(aResults), - mCount(0) + mResults(aResults) { } nsIPresContext* mPresContext; @@ -438,20 +538,16 @@ struct RulesMatchingData { nsIContent* mContent; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; - }; static PRBool -EnumRulesMatching(nsISupports* aSheet, void* aData) +EnumRulesMatching(nsISupports* aProcessor, void* aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; RulesMatchingData* data = (RulesMatchingData*)aData; - if (NS_OK == sheet->UseForMedium(data->mMedium)) { - data->mCount += sheet->RulesMatching(data->mPresContext, data->mContent, - data->mParentContext, data->mResults); - } + processor->RulesMatching(data->mPresContext, data->mMedium, data->mContent, + data->mParentContext, data->mResults); return PR_TRUE; } @@ -483,7 +579,7 @@ nsIStyleContext* StyleSetImpl::GetContext(nsIPresContext* aPresContext, } // XXX for now only works for strength 0 & 1 -static void SortRulesByStrength(nsISupportsArray* aRules, PRInt32& aBackstopRuleCount) +static void SortRulesByStrength(nsISupportsArray* aRules) { PRUint32 cnt; nsresult rv = aRules->Count(&cnt); @@ -500,9 +596,6 @@ static void SortRulesByStrength(nsISupportsArray* aRules, PRInt32& aBackstopRule aRules->RemoveElementAt(index); aRules->AppendElement(rule); count--; - if (index < aBackstopRuleCount) { - aBackstopRuleCount--; - } } else { index++; @@ -534,47 +627,39 @@ nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext, NS_ASSERTION(aPresContext, "must have pres context"); if (aContent && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + RulesMatchingData data(aPresContext, medium, aContent, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - RulesMatchingData data(aPresContext, medium, aContent, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, nsnull, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount = 0; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, nsnull, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); + result = GetContext(aPresContext, aParentContext, nsnull, nsnull, aForceUnique, usedRules); } + NS_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - result = GetContext(aPresContext, aParentContext, nsnull, nsnull, aForceUnique, usedRules); - } - NS_RELEASE(medium); } } @@ -594,8 +679,7 @@ struct PseudoRulesMatchingData { mParentContent(aParentContent), mPseudoTag(aPseudoTag), mParentContext(aParentContext), - mResults(aResults), - mCount(0) + mResults(aResults) { } nsIPresContext* mPresContext; @@ -604,21 +688,17 @@ struct PseudoRulesMatchingData { nsIAtom* mPseudoTag; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; - }; static PRBool -EnumPseudoRulesMatching(nsISupports* aSheet, void* aData) +EnumPseudoRulesMatching(nsISupports* aProcessor, void* aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; PseudoRulesMatchingData* data = (PseudoRulesMatchingData*)aData; - if (NS_OK == sheet->UseForMedium(data->mMedium)) { - data->mCount += sheet->RulesMatching(data->mPresContext, data->mParentContent, - data->mPseudoTag, - data->mParentContext, data->mResults); - } + processor->RulesMatching(data->mPresContext, data->mMedium, + data->mParentContent, data->mPseudoTag, + data->mParentContext, data->mResults); return PR_TRUE; } @@ -635,48 +715,41 @@ nsIStyleContext* StyleSetImpl::ResolvePseudoStyleFor(nsIPresContext* aPresContex NS_ASSERTION(aPresContext, "must have pres context"); if (aPseudoTag && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + PseudoRulesMatchingData data(aPresContext, medium, aParentContent, + aPseudoTag, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumPseudoRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - PseudoRulesMatchingData data(aPresContext, medium, aParentContent, - aPseudoTag, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount = 0; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + rules->Clear(); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, nsnull, aForceUnique, usedRules); } + NS_IF_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - result = GetContext(aPresContext, aParentContext, aPseudoTag, nsnull, aForceUnique, usedRules); - } - NS_IF_RELEASE(medium); } } @@ -697,47 +770,40 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, NS_ASSERTION(aPresContext, "must have pres context"); if (aPseudoTag && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + PseudoRulesMatchingData data(aPresContext, medium, aParentContent, + aPseudoTag, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumPseudoRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - PseudoRulesMatchingData data(aPresContext, medium, aParentContent, - aPseudoTag, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + rules->Clear(); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); } + NS_IF_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - } - NS_IF_RELEASE(medium); } } @@ -780,12 +846,7 @@ StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, else { // need to make one in the new parent nsISupportsArray* newRules = nsnull; if (rules) { - newRules = mRecycler; - mRecycler = nsnull; - if (! newRules) { - result = NS_NewISupportsArray(&newRules); - } - if (newRules) { + if (EnsureArray(&newRules)) { newRules->AppendElements(rules); } } @@ -804,21 +865,24 @@ StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, } struct StatefulData { - StatefulData(nsIPresContext* aPresContext, nsIContent* aContent) + StatefulData(nsIPresContext* aPresContext, nsIAtom* aMedium, nsIContent* aContent) : mPresContext(aPresContext), + mMedium(aMedium), mContent(aContent), mStateful(PR_FALSE) {} nsIPresContext* mPresContext; + nsIAtom* mMedium; nsIContent* mContent; PRBool mStateful; }; -static PRBool SheetHasStatefulStyle(nsISupports* aElement, void *aData) +static PRBool SheetHasStatefulStyle(nsISupports* aProcessor, void *aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aElement; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; StatefulData* data = (StatefulData*)aData; - if (NS_OK == sheet->HasStateDependentStyle(data->mPresContext, data->mContent)) { + if (NS_OK == processor->HasStateDependentStyle(data->mPresContext, data->mMedium, + data->mContent)) { data->mStateful = PR_TRUE; return PR_FALSE; // stop iteration } @@ -830,17 +894,18 @@ NS_IMETHODIMP StyleSetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent) { - StatefulData data(aPresContext, aContent); - if (mBackstopSheets) { - mBackstopSheets->EnumerateForwards(SheetHasStatefulStyle, &data); + if (! mRuleProcessors) { + GatherRuleProcessors(); } - if (mDocSheets && (! data.mStateful)) { - mDocSheets->EnumerateForwards(SheetHasStatefulStyle, &data); + if (mRuleProcessors) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + StatefulData data(aPresContext, medium, aContent); + mRuleProcessors->EnumerateForwards(SheetHasStatefulStyle, &data); + NS_IF_RELEASE(medium); + return ((data.mStateful) ? NS_OK : NS_COMFALSE); } - if (mOverrideSheets && (! data.mStateful)) { - mOverrideSheets->EnumerateForwards(SheetHasStatefulStyle, &data); - } - return ((data.mStateful) ? NS_OK : NS_COMFALSE); + return NS_COMFALSE; } diff --git a/mozilla/content/html/style/public/nsICSSStyleSheet.h b/mozilla/content/html/style/public/nsICSSStyleSheet.h index 892d5083d47..24664c1e581 100644 --- a/mozilla/content/html/style/public/nsICSSStyleSheet.h +++ b/mozilla/content/html/style/public/nsICSSStyleSheet.h @@ -24,6 +24,7 @@ class nsICSSRule; class nsIDOMNode; class nsINameSpace; +class nsICSSStyleRuleProcessor; // IID for the nsICSSStyleSheet interface {8f83b0f0-b21a-11d1-8031-006008159b5a} #define NS_ICSS_STYLE_SHEET_IID \ @@ -62,6 +63,8 @@ public: NS_IMETHOD IsUnmodified(void) const = 0; // NS_OK if not modified since construct/last reset, NS_COMFALSE otherwise NS_IMETHOD SetModified(PRBool aModified) = 0; + + NS_IMETHOD DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor) = 0; }; // XXX for backwards compatibility and convenience diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp index 82ea400bf22..49bb428c98c 100644 --- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp @@ -30,6 +30,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #endif // NECKO #include "nsISupportsArray.h" #include "nsHashtable.h" +#include "nsICSSStyleRuleProcessor.h" #include "nsICSSStyleRule.h" #include "nsICSSNameSpaceRule.h" #include "nsICSSMediaRule.h" @@ -418,6 +419,7 @@ class CSSStyleRuleCollectionImpl; class CSSStyleSheetImpl : public nsICSSStyleSheet, public nsIDOMCSSStyleSheet, + public nsIStyleRuleProcessor, public nsIScriptObjectOwner { public: void* operator new(size_t size); @@ -451,19 +453,26 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); NS_IMETHOD SetOwningNode(nsIDOMNode* aOwningNode); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); + NS_IMETHOD DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // style rule processor API XXX will move to seperate class + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent); NS_IMETHOD ContainsStyleSheet(nsIURI* aURL) const; @@ -1219,6 +1228,21 @@ nsresult CSSStyleSheetImpl::QueryInterface(const nsIID& aIID, return NS_NOINTERFACE; } +NS_IMETHODIMP +CSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor) +{ + aProcessor = this; // XXX temp until rule processing gets factored + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +CSSStyleSheetImpl::DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor) +{ + return NS_OK; +} + static const PRUnichar kNullCh = PRUnichar('\0'); static PRBool ValueIncludes(const nsString& aValueList, const nsString& aValue, PRBool aCaseSensitive) @@ -1585,14 +1609,12 @@ struct ContentEnumData { mContent = aContent; mParentContext = aParentContext; mResults = aResults; - mCount = 0; } nsIPresContext* mPresContext; nsIContent* mContent; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; }; static PRBool SelectorMatchesTree(nsIPresContext* aPresContext, @@ -1662,12 +1684,10 @@ static void ContentEnumFunc(nsICSSStyleRule* aRule, void* aData) nsIStyleRule* iRule; if (NS_OK == aRule->QueryInterface(kIStyleRuleIID, (void**)&iRule)) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); iRule = aRule->GetImportantRule(); if (nsnull != iRule) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); } } @@ -1683,22 +1703,18 @@ static PRBool ContentEnumWrap(nsISupports* aRule, void* aData) } #endif -PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - - nsIAtom* presMedium = nsnull; - - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { ContentEnumData data(aPresContext, aContent, aParentContext, aResults); @@ -1715,7 +1731,6 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } cascade->mRuleHash.EnumerateAllRules(tagAtom, idAtom, classArray, ContentEnumFunc, &data); - matchCount += data.mCount; #ifdef DEBUG_RULES nsISupportsArray* list1; @@ -1735,8 +1750,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_IF_RELEASE(tagAtom); NS_IF_RELEASE(idAtom); } - NS_IF_RELEASE(presMedium); - return matchCount; + return NS_OK; } struct PseudoEnumData { @@ -1749,7 +1763,6 @@ struct PseudoEnumData { mPseudoTag = aPseudoTag; mParentContext = aParentContext; mResults = aResults; - mCount = 0; } nsIPresContext* mPresContext; @@ -1757,7 +1770,6 @@ struct PseudoEnumData { nsIAtom* mPseudoTag; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; }; static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData) @@ -1790,12 +1802,10 @@ static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData) nsIStyleRule* iRule; if (NS_OK == aRule->QueryInterface(kIStyleRuleIID, (void**)&iRule)) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); iRule = aRule->GetImportantRule(); if (nsnull != iRule) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); } } @@ -1810,27 +1820,23 @@ static PRBool PseudoEnumWrap(nsISupports* aRule, void* aData) } #endif -PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aPseudoTag, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - - nsIAtom* presMedium = nsnull; - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aParentContext, aResults); cascade->mRuleHash.EnumerateTagRules(aPseudoTag, PseudoEnumFunc, &data); - matchCount += data.mCount; #ifdef DEBUG_RULES nsISupportsArray* list1; @@ -1846,8 +1852,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_RELEASE(list2); #endif } - NS_IF_RELEASE(presMedium); - return matchCount; + return NS_OK; } struct StateEnumData @@ -1878,21 +1883,18 @@ PRBool StateEnumFunc(void* aSelector, void* aData) // Test if style is dependent on content state NS_IMETHODIMP CSSStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { PRBool isStateful = PR_FALSE; - nsIAtom* presMedium = nsnull; - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { // look up content in state rule list StateEnumData data(aPresContext, aContent); isStateful = (! cascade->mStateSelectors.EnumerateForwards(StateEnumFunc, &data)); // if stopped, have state } - NS_IF_RELEASE(presMedium); return ((isStateful) ? NS_OK : NS_COMFALSE); } @@ -2587,12 +2589,10 @@ GatherStyleRulesForMedium(nsISupports* aRule, void* aData) nsresult CSSStyleSheetImpl::GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules) { - if (aRules) { + if (aRules && (NS_OK == UseForMedium(aMedium))) { CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - if (NS_OK == child->UseForMedium(aMedium)) { - child->GatherRulesFor(aMedium, aRules); - } + child->GatherRulesFor(aMedium, aRules); child = child->mNext; } @@ -2656,13 +2656,11 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) nsresult CSSStyleSheetImpl::SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) { - if (aRules) { + if (aRules && (NS_OK == UseForMedium(aMedium))) { // get child rules first CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - if (NS_OK == child->UseForMedium(aMedium)) { - child->SlowCascadeRulesInto(aMedium, aRules); - } + child->SlowCascadeRulesInto(aMedium, aRules); child = child->mNext; } diff --git a/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp index a33e4f23ca9..ae846ea82b2 100644 --- a/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp @@ -28,6 +28,7 @@ #include "nsIFrame.h" #include "nsHTMLIIDs.h" #include "nsICSSStyleRule.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleContext.h" #include "nsIPresContext.h" #include "nsIDocument.h" @@ -258,7 +259,8 @@ CSSFirstLetterRule::MapStyleInto(nsIStyleContext* aContext, // ----------------------------------------------------------- -class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet { +class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet, + public nsIStyleRuleProcessor { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); @@ -288,19 +290,26 @@ public: NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const; NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // nsIStyleRuleProcessor api + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); + + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent); // XXX style rule enumerations @@ -410,25 +419,39 @@ nsresult HTMLCSSStyleSheetImpl::QueryInterface(const nsIID& aIID, NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIStyleRuleProcessor::GetIID())) { + *aInstancePtrResult = (void*) ((nsIStyleRuleProcessor*)this); + NS_ADDREF_THIS(); + return NS_OK; + } if (aIID.Equals(kISupportsIID)) { - *aInstancePtrResult = (void*) ((nsISupports*)this); + *aInstancePtrResult = (void*) ((nsISupports*)(nsIStyleSheet*)this); NS_ADDREF_THIS(); return NS_OK; } return NS_NOINTERFACE; } -PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* /*aPrevProcessor*/) +{ + aProcessor = this; + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - nsIStyledContent* styledContent; // just get the one and only style rule from the content's STYLE attribute @@ -440,13 +463,11 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, aResults->Count(&postCount); while (index < postCount) { nsIStyleRule* rule = (nsIStyleRule*)aResults->ElementAt(index++); - matchCount++; nsICSSStyleRule* cssRule; if (NS_SUCCEEDED(rule->QueryInterface(kICSSStyleRuleIID, (void**)&cssRule))) { nsIStyleRule* important = cssRule->GetImportantRule(); if (nsnull != important) { aResults->AppendElement(important); - matchCount++; NS_RELEASE(important); } NS_RELEASE(cssRule); @@ -458,14 +479,16 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_RELEASE(styledContent); } - return matchCount; + return NS_OK; } -PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { if (aPseudoTag == nsHTMLAtoms::firstLinePseudo) { PRUint32 cnt; @@ -479,7 +502,7 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } if (mFirstLineRule) { aResults->AppendElement(mFirstLineRule); - return 1; + return NS_OK; } } } @@ -495,12 +518,12 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } if (mFirstLetterRule) { aResults->AppendElement(mFirstLetterRule); - return 1; + return NS_OK; } } } // else no pseudo frame style... - return 0; + return NS_OK; } NS_IMETHODIMP @@ -522,6 +545,7 @@ HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) // Test if style is dependent on content state NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { return NS_COMFALSE; diff --git a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp index c5c8b39ec57..acd6004591e 100644 --- a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp @@ -32,6 +32,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsHashtable.h" #include "nsIHTMLContent.h" #include "nsIHTMLAttributes.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleRule.h" #include "nsIFrame.h" #include "nsIStyleContext.h" @@ -259,21 +260,25 @@ TableBackgroundRule::MapFontStyleInto(nsIStyleContext* aContext, nsIPresContext* NS_IMETHODIMP TableBackgroundRule::MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext) { - nsStyleColor* styleColor; - styleColor = (nsStyleColor*)aContext->GetMutableStyleData(eStyleStruct_Color); - nsIStyleContext* parentContext = aContext->GetParent(); - const nsStyleColor* parentStyleColor; - parentStyleColor = (const nsStyleColor*)parentContext->GetStyleData(eStyleStruct_Color); - if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) { - styleColor->mBackgroundColor = parentStyleColor->mBackgroundColor; - styleColor->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; - } + if (parentContext) { + nsStyleColor* styleColor; + styleColor = (nsStyleColor*)aContext->GetMutableStyleData(eStyleStruct_Color); - if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE)) { - styleColor->mBackgroundImage = parentStyleColor->mBackgroundImage; - styleColor->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; + const nsStyleColor* parentStyleColor; + parentStyleColor = (const nsStyleColor*)parentContext->GetStyleData(eStyleStruct_Color); + + if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) { + styleColor->mBackgroundColor = parentStyleColor->mBackgroundColor; + styleColor->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; + } + + if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE)) { + styleColor->mBackgroundImage = parentStyleColor->mBackgroundImage; + styleColor->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; + } + NS_RELEASE(parentContext); } return NS_OK; @@ -356,7 +361,8 @@ nsHashKey* AttributeKey::Clone(void) const // ----------------------------------------------------------- -class HTMLStyleSheetImpl : public nsIHTMLStyleSheet { +class HTMLStyleSheetImpl : public nsIHTMLStyleSheet, + public nsIStyleRuleProcessor { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); @@ -385,19 +391,26 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocumemt); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // nsIStyleRuleProcessor API + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); + + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent); // nsIHTMLStyleSheet api NS_IMETHOD Init(nsIURI* aURL, nsIDocument* aDocument); @@ -561,6 +574,11 @@ nsresult HTMLStyleSheetImpl::QueryInterface(const nsIID& aIID, NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIStyleRuleProcessor::GetIID())) { + *aInstancePtrResult = (void*) ((nsIStyleRuleProcessor*)this); + NS_ADDREF_THIS(); + return NS_OK; + } if (aIID.Equals(kIStyleFrameConstructionIID)) { // XXX this breaks XPCOM rules since it isn't a proper delegate // This is a temporary method of connecting the constructor for now @@ -583,17 +601,26 @@ nsresult HTMLStyleSheetImpl::QueryInterface(const nsIID& aIID, return NS_NOINTERFACE; } -PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* /*aPrevProcessor*/) +{ + aProcessor = this; + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - nsIStyledContent* styledContent; if (NS_SUCCEEDED(aContent->QueryInterface(nsIStyledContent::GetIID(), (void**)&styledContent))) { PRInt32 nameSpace; @@ -616,7 +643,6 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (! linkHandler) { if (nsnull != mLinkRule) { aResults->AppendElement(mLinkRule); - matchCount++; } } else { @@ -647,13 +673,11 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, case eLinkState_Unvisited: if (nsnull != mLinkRule) { aResults->AppendElement(mLinkRule); - matchCount++; } break; case eLinkState_Visited: if (nsnull != mVisitedRule) { aResults->AppendElement(mVisitedRule); - matchCount++; } break; default: @@ -676,7 +700,6 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (NS_OK == eventStateManager->GetContentState(aContent, state)) { if (0 != (state & NS_EVENT_STATE_ACTIVE)) { aResults->AppendElement(mActiveRule); - matchCount++; } } NS_RELEASE(eventStateManager); @@ -695,38 +718,31 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (eCompatibility_NavQuirks == mode) { if (mDocumentColorRule) { aResults->AppendElement(mDocumentColorRule); - matchCount++; } aResults->AppendElement(mTableBackgroundRule); - matchCount++; } } else if (tag == nsHTMLAtoms::html) { if (mDocumentColorRule) { aResults->AppendElement(mDocumentColorRule); - matchCount++; } } NS_IF_RELEASE(tag); } // end html namespace - // just get the one and only style rule from the content - PRUint32 preCount = 0; - PRUint32 postCount = 0; - aResults->Count(&preCount); + // just get the style rules from the content styledContent->GetContentStyleRules(aResults); - aResults->Count(&postCount); - matchCount += (postCount - preCount); NS_RELEASE(styledContent); } - return matchCount; + return NS_OK; } // Test if style is dependent on content state NS_IMETHODIMP HTMLStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { nsresult result = NS_COMFALSE; @@ -757,14 +773,16 @@ HTMLStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, -PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { // no pseudo frame style - return 0; + return NS_OK; } diff --git a/mozilla/content/html/style/src/nsICSSStyleRuleProcessor.h b/mozilla/content/html/style/src/nsICSSStyleRuleProcessor.h new file mode 100644 index 00000000000..29b88c1705e --- /dev/null +++ b/mozilla/content/html/style/src/nsICSSStyleRuleProcessor.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsICSSStyleRuleProcessor_h___ +#define nsICSSStyleRuleProcessor_h___ + +#include "nslayout.h" +#include "nsIStyleRuleProcessor.h" + +class nsICSSStyleSheet; + +// IID for the nsICSSStyleRuleProcessor interface {98bf169c-7b7c-11d3-ba05-001083023c2b} +#define NS_ICSS_STYLE_RULE_PROCESSOR_IID \ +{0x98bf169c, 0x7b7c, 0x11d3, {0xba, 0x05, 0x00, 0x10, 0x83, 0x02, 0x3c, 0x2b}} + +/* The CSS style rule processor provides a mechanism for sibling style sheets + * to combine their rule processing in order to allow proper cascading to happen. + * + * When queried for a rule processor, a CSS style sheet will append itself to + * the previous CSS processor if present, and return nsnull. Otherwise it will + * create a new processor for itself. + * + * CSS style rule processors keep a live reference on all style sheets bound to them + * The CSS style sheets keep a weak reference on all the processors that they are + * bound to (many to many). The CSS style sheet is told when the rule processor is + * going away (via DropRuleProcessorReference). + */ +class nsICSSStyleRuleProcessor: public nsIStyleRuleProcessor { +public: + static const nsIID& GetIID() { static nsIID iid = NS_ICSS_STYLE_RULE_PROCESSOR_IID; return iid; } + + NS_IMETHOD AppendStyleSheet(nsICSSStyleSheet* aStyleSheet) = 0; +}; + +#endif /* nsICSSStyleRuleProcessor_h___ */ diff --git a/mozilla/layout/base/public/MANIFEST b/mozilla/layout/base/public/MANIFEST index 77220d14c44..5908bf6090b 100644 --- a/mozilla/layout/base/public/MANIFEST +++ b/mozilla/layout/base/public/MANIFEST @@ -40,6 +40,7 @@ nsIStyleRule.h nsIStyleSet.h nsIStyleSheet.h nsIStyleSheetLinkingElement.h +nsIStyleRuleProcessor.h nsITextContent.h nsTextFragment.h nsIAnonymousContent.h diff --git a/mozilla/layout/base/public/Makefile.in b/mozilla/layout/base/public/Makefile.in index f538b75df24..7e99a61d7e5 100644 --- a/mozilla/layout/base/public/Makefile.in +++ b/mozilla/layout/base/public/Makefile.in @@ -57,6 +57,7 @@ nsIStyleRule.h \ nsIStyleSet.h \ nsIStyleSheet.h \ nsIStyleSheetLinkingElement.h \ +nsIStyleRuleProcessor.h \ nsITextContent.h \ nsLayoutAtoms.h \ nsLayoutAtomList.h \ diff --git a/mozilla/layout/base/public/makefile.win b/mozilla/layout/base/public/makefile.win index 14cbc3917fa..d2813915f20 100644 --- a/mozilla/layout/base/public/makefile.win +++ b/mozilla/layout/base/public/makefile.win @@ -50,6 +50,7 @@ EXPORTS = \ nsIStyleSet.h \ nsIStyleSheet.h \ nsIStyleSheetLinkingElement.h \ + nsIStyleRuleProcessor.h \ nsITextContent.h \ nsLayoutAtoms.h \ nsLayoutAtomList.h \ diff --git a/mozilla/layout/base/public/nsIStyleRuleProcessor.h b/mozilla/layout/base/public/nsIStyleRuleProcessor.h new file mode 100644 index 00000000000..ff317a9445a --- /dev/null +++ b/mozilla/layout/base/public/nsIStyleRuleProcessor.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsIStyleRuleProcessor_h___ +#define nsIStyleRuleProcessor_h___ + +#include + +#include "nslayout.h" +#include "nsISupports.h" + +class nsIStyleSheet; +class nsIStyleContext; +class nsIPresContext; +class nsIContent; +class nsISupportsArray; +class nsIAtom; + +// IID for the nsIStyleRuleProcessor interface {015575fe-7b6c-11d3-ba05-001083023c2b} +#define NS_ISTYLE_RULE_PROCESSOR_IID \ +{0x015575fe, 0x7b6c, 0x11d3, {0xba, 0x05, 0x00, 0x10, 0x83, 0x02, 0x3c, 0x2b}} + +/* The style rule processor interface is a mechanism to seperate the matching + * of style rules from style sheet instances. + * Simple style sheets can and will act as their own processor. + * Sheets where rule ordering interlaces between multiple sheets, will need to + * share a single rule processor between them (CSS sheets do this for cascading order) + */ +class nsIStyleRuleProcessor : public nsISupports { +public: + static const nsIID& GetIID() { static nsIID iid = NS_ISTYLE_RULE_PROCESSOR_IID; return iid; } + + // populate supports array with nsIStyleRule* + // rules are ordered, those with higher precedence come last + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) = 0; + + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) = 0; + + // Test if style is dependent on content state + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent) = 0; +}; + +#endif /* nsIStyleRuleProcessor_h___ */ diff --git a/mozilla/layout/base/public/nsIStyleSheet.h b/mozilla/layout/base/public/nsIStyleSheet.h index 1a630e76698..dcbf8be9305 100644 --- a/mozilla/layout/base/public/nsIStyleSheet.h +++ b/mozilla/layout/base/public/nsIStyleSheet.h @@ -29,6 +29,7 @@ class nsIPresContext; class nsIContent; class nsIDocument; class nsIStyleContext; +class nsIStyleRuleProcessor; // IID for the nsIStyleSheet interface {8c4a80a0-ad6a-11d1-8031-006008159b5a} #define NS_ISTYLE_SHEET_IID \ @@ -54,22 +55,9 @@ public: NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const = 0; // may be null NS_IMETHOD SetOwningDocument(nsIDocument* aDocument) = 0; - // populate supports array with nsIStyleRule* - // rules are ordered, those with higher precedence come last - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) = 0; - - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) = 0; - - // Test if style is dependent on content state - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent) = 0; + // style rule processor access + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor) = 0; // XXX style rule enumerations diff --git a/mozilla/layout/base/src/nsStyleSet.cpp b/mozilla/layout/base/src/nsStyleSet.cpp index 0fa87d6d040..69a94c90558 100644 --- a/mozilla/layout/base/src/nsStyleSet.cpp +++ b/mozilla/layout/base/src/nsStyleSet.cpp @@ -18,6 +18,7 @@ #include "nsCOMPtr.h" #include "nsIStyleSet.h" #include "nsIStyleSheet.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleRule.h" #include "nsIStyleContext.h" #include "nsISupportsArray.h" @@ -174,15 +175,22 @@ private: protected: virtual ~StyleSetImpl(); PRBool EnsureArray(nsISupportsArray** aArray); + void RecycleArray(nsISupportsArray** aArray); + void ClearRuleProcessors(void); + nsresult GatherRuleProcessors(void); + nsIStyleContext* GetContext(nsIPresContext* aPresContext, nsIStyleContext* aParentContext, nsIAtom* aPseudoTag, nsISupportsArray* aRules, PRBool aForceUnique, PRBool& aUsedRules); void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets); void ListContexts(nsIStyleContext* aRootContext, FILE* out, PRInt32 aIndent); - nsISupportsArray* mOverrideSheets; - nsISupportsArray* mDocSheets; - nsISupportsArray* mBackstopSheets; + nsISupportsArray* mOverrideSheets; // most significant first + nsISupportsArray* mDocSheets; // " " + nsISupportsArray* mBackstopSheets; // " " + + nsISupportsArray* mRuleProcessors; // least significant first + nsISupportsArray* mRecycler; nsIStyleFrameConstruction* mFrameConstructor; @@ -198,6 +206,7 @@ StyleSetImpl::StyleSetImpl() : mOverrideSheets(nsnull), mDocSheets(nsnull), mBackstopSheets(nsnull), + mRuleProcessors(nsnull), mRecycler(nsnull), mFrameConstructor(nsnull) { @@ -211,6 +220,7 @@ StyleSetImpl::~StyleSetImpl() NS_IF_RELEASE(mOverrideSheets); NS_IF_RELEASE(mDocSheets); NS_IF_RELEASE(mBackstopSheets); + NS_IF_RELEASE(mRuleProcessors); NS_IF_RELEASE(mFrameConstructor); NS_IF_RELEASE(mRecycler); } @@ -224,13 +234,94 @@ NS_IMPL_ISUPPORTS2(StyleSetImpl, nsIStyleSet, nsITimeRecorder) PRBool StyleSetImpl::EnsureArray(nsISupportsArray** aArray) { if (nsnull == *aArray) { - if (NS_OK != NS_NewISupportsArray(aArray)) { - return PR_FALSE; + (*aArray) = mRecycler; + mRecycler = nsnull; + if (nsnull == *aArray) { + if (NS_OK != NS_NewISupportsArray(aArray)) { + return PR_FALSE; + } } } return PR_TRUE; } +void +StyleSetImpl::RecycleArray(nsISupportsArray** aArray) +{ + if (! mRecycler) { + mRecycler = *aArray; // take ref + mRecycler->Clear(); + *aArray = nsnull; + } + else { // already have a recycled array + NS_RELEASE(*aArray); + } +} + +void +StyleSetImpl::ClearRuleProcessors(void) +{ + if (mRuleProcessors) { + RecycleArray(&mRuleProcessors); + } +} + +struct RuleProcessorData { + RuleProcessorData(nsISupportsArray* aRuleProcessors) + : mRuleProcessors(aRuleProcessors), + mPrevProcessor(nsnull) + {} + + nsISupportsArray* mRuleProcessors; + nsIStyleRuleProcessor* mPrevProcessor; +}; + +static PRBool +EnumRuleProcessor(nsISupports* aSheet, void* aData) +{ + nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + RuleProcessorData* data = (RuleProcessorData*)aData; + + nsIStyleRuleProcessor* processor = nsnull; + nsresult result = sheet->GetStyleRuleProcessor(processor, data->mPrevProcessor); + if (NS_SUCCEEDED(result) && processor) { + if (processor != data->mPrevProcessor) { + data->mRuleProcessors->AppendElement(processor); + data->mPrevProcessor = processor; // ref is held by array + } + NS_RELEASE(processor); + } + return PR_TRUE; +} + +nsresult +StyleSetImpl::GatherRuleProcessors(void) +{ + nsresult result = NS_ERROR_OUT_OF_MEMORY; + if (EnsureArray(&mRuleProcessors)) { + RuleProcessorData data(mRuleProcessors); + if (mBackstopSheets) { + mBackstopSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + if (mDocSheets) { + data.mPrevProcessor = nsnull; + mDocSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + if (mOverrideSheets) { + data.mPrevProcessor = nsnull; + mOverrideSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + result = NS_OK; + PRUint32 count; + mRuleProcessors->Count(&count); + if (0 == count) { + RecycleArray(&mRuleProcessors); + } + } + return result; +} + + // ----- Override sheets void StyleSetImpl::AppendOverrideStyleSheet(nsIStyleSheet* aSheet) @@ -239,6 +330,7 @@ void StyleSetImpl::AppendOverrideStyleSheet(nsIStyleSheet* aSheet) if (EnsureArray(&mOverrideSheets)) { mOverrideSheets->RemoveElement(aSheet); mOverrideSheets->AppendElement(aSheet); + ClearRuleProcessors(); } } @@ -250,6 +342,7 @@ void StyleSetImpl::InsertOverrideStyleSheetAfter(nsIStyleSheet* aSheet, mOverrideSheets->RemoveElement(aSheet); PRInt32 index = mOverrideSheets->IndexOf(aAfterSheet); mOverrideSheets->InsertElementAt(aSheet, ++index); + ClearRuleProcessors(); } } @@ -261,6 +354,7 @@ void StyleSetImpl::InsertOverrideStyleSheetBefore(nsIStyleSheet* aSheet, mOverrideSheets->RemoveElement(aSheet); PRInt32 index = mOverrideSheets->IndexOf(aBeforeSheet); mOverrideSheets->InsertElementAt(aSheet, ((-1 < index) ? index : 0)); + ClearRuleProcessors(); } } @@ -270,6 +364,7 @@ void StyleSetImpl::RemoveOverrideStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mOverrideSheets) { mOverrideSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -325,6 +420,7 @@ void StyleSetImpl::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocumen if (nsnull == mFrameConstructor) { aSheet->QueryInterface(kIStyleFrameConstructionIID, (void **)&mFrameConstructor); } + ClearRuleProcessors(); } } @@ -334,6 +430,7 @@ void StyleSetImpl::RemoveDocStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mDocSheets) { mDocSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -365,6 +462,7 @@ void StyleSetImpl::AppendBackstopStyleSheet(nsIStyleSheet* aSheet) if (EnsureArray(&mBackstopSheets)) { mBackstopSheets->RemoveElement(aSheet); mBackstopSheets->AppendElement(aSheet); + ClearRuleProcessors(); } } @@ -376,6 +474,7 @@ void StyleSetImpl::InsertBackstopStyleSheetAfter(nsIStyleSheet* aSheet, mBackstopSheets->RemoveElement(aSheet); PRInt32 index = mBackstopSheets->IndexOf(aAfterSheet); mBackstopSheets->InsertElementAt(aSheet, ++index); + ClearRuleProcessors(); } } @@ -387,6 +486,7 @@ void StyleSetImpl::InsertBackstopStyleSheetBefore(nsIStyleSheet* aSheet, mBackstopSheets->RemoveElement(aSheet); PRInt32 index = mBackstopSheets->IndexOf(aBeforeSheet); mBackstopSheets->InsertElementAt(aSheet, ((-1 < index) ? index : 0)); + ClearRuleProcessors(); } } @@ -396,6 +496,7 @@ void StyleSetImpl::RemoveBackstopStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mBackstopSheets) { mBackstopSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -429,8 +530,7 @@ struct RulesMatchingData { mMedium(aMedium), mContent(aContent), mParentContext(aParentContext), - mResults(aResults), - mCount(0) + mResults(aResults) { } nsIPresContext* mPresContext; @@ -438,20 +538,16 @@ struct RulesMatchingData { nsIContent* mContent; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; - }; static PRBool -EnumRulesMatching(nsISupports* aSheet, void* aData) +EnumRulesMatching(nsISupports* aProcessor, void* aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; RulesMatchingData* data = (RulesMatchingData*)aData; - if (NS_OK == sheet->UseForMedium(data->mMedium)) { - data->mCount += sheet->RulesMatching(data->mPresContext, data->mContent, - data->mParentContext, data->mResults); - } + processor->RulesMatching(data->mPresContext, data->mMedium, data->mContent, + data->mParentContext, data->mResults); return PR_TRUE; } @@ -483,7 +579,7 @@ nsIStyleContext* StyleSetImpl::GetContext(nsIPresContext* aPresContext, } // XXX for now only works for strength 0 & 1 -static void SortRulesByStrength(nsISupportsArray* aRules, PRInt32& aBackstopRuleCount) +static void SortRulesByStrength(nsISupportsArray* aRules) { PRUint32 cnt; nsresult rv = aRules->Count(&cnt); @@ -500,9 +596,6 @@ static void SortRulesByStrength(nsISupportsArray* aRules, PRInt32& aBackstopRule aRules->RemoveElementAt(index); aRules->AppendElement(rule); count--; - if (index < aBackstopRuleCount) { - aBackstopRuleCount--; - } } else { index++; @@ -534,47 +627,39 @@ nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext, NS_ASSERTION(aPresContext, "must have pres context"); if (aContent && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + RulesMatchingData data(aPresContext, medium, aContent, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - RulesMatchingData data(aPresContext, medium, aContent, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, nsnull, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount = 0; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, nsnull, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); + result = GetContext(aPresContext, aParentContext, nsnull, nsnull, aForceUnique, usedRules); } + NS_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - result = GetContext(aPresContext, aParentContext, nsnull, nsnull, aForceUnique, usedRules); - } - NS_RELEASE(medium); } } @@ -594,8 +679,7 @@ struct PseudoRulesMatchingData { mParentContent(aParentContent), mPseudoTag(aPseudoTag), mParentContext(aParentContext), - mResults(aResults), - mCount(0) + mResults(aResults) { } nsIPresContext* mPresContext; @@ -604,21 +688,17 @@ struct PseudoRulesMatchingData { nsIAtom* mPseudoTag; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; - }; static PRBool -EnumPseudoRulesMatching(nsISupports* aSheet, void* aData) +EnumPseudoRulesMatching(nsISupports* aProcessor, void* aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; PseudoRulesMatchingData* data = (PseudoRulesMatchingData*)aData; - if (NS_OK == sheet->UseForMedium(data->mMedium)) { - data->mCount += sheet->RulesMatching(data->mPresContext, data->mParentContent, - data->mPseudoTag, - data->mParentContext, data->mResults); - } + processor->RulesMatching(data->mPresContext, data->mMedium, + data->mParentContent, data->mPseudoTag, + data->mParentContext, data->mResults); return PR_TRUE; } @@ -635,48 +715,41 @@ nsIStyleContext* StyleSetImpl::ResolvePseudoStyleFor(nsIPresContext* aPresContex NS_ASSERTION(aPresContext, "must have pres context"); if (aPseudoTag && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + PseudoRulesMatchingData data(aPresContext, medium, aParentContent, + aPseudoTag, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumPseudoRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - PseudoRulesMatchingData data(aPresContext, medium, aParentContent, - aPseudoTag, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount = 0; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + rules->Clear(); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, nsnull, aForceUnique, usedRules); } + NS_IF_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - result = GetContext(aPresContext, aParentContext, aPseudoTag, nsnull, aForceUnique, usedRules); - } - NS_IF_RELEASE(medium); } } @@ -697,47 +770,40 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, NS_ASSERTION(aPresContext, "must have pres context"); if (aPseudoTag && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + PseudoRulesMatchingData data(aPresContext, medium, aParentContent, + aPseudoTag, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumPseudoRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - PseudoRulesMatchingData data(aPresContext, medium, aParentContent, - aPseudoTag, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + rules->Clear(); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); } + NS_IF_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - } - NS_IF_RELEASE(medium); } } @@ -780,12 +846,7 @@ StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, else { // need to make one in the new parent nsISupportsArray* newRules = nsnull; if (rules) { - newRules = mRecycler; - mRecycler = nsnull; - if (! newRules) { - result = NS_NewISupportsArray(&newRules); - } - if (newRules) { + if (EnsureArray(&newRules)) { newRules->AppendElements(rules); } } @@ -804,21 +865,24 @@ StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, } struct StatefulData { - StatefulData(nsIPresContext* aPresContext, nsIContent* aContent) + StatefulData(nsIPresContext* aPresContext, nsIAtom* aMedium, nsIContent* aContent) : mPresContext(aPresContext), + mMedium(aMedium), mContent(aContent), mStateful(PR_FALSE) {} nsIPresContext* mPresContext; + nsIAtom* mMedium; nsIContent* mContent; PRBool mStateful; }; -static PRBool SheetHasStatefulStyle(nsISupports* aElement, void *aData) +static PRBool SheetHasStatefulStyle(nsISupports* aProcessor, void *aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aElement; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; StatefulData* data = (StatefulData*)aData; - if (NS_OK == sheet->HasStateDependentStyle(data->mPresContext, data->mContent)) { + if (NS_OK == processor->HasStateDependentStyle(data->mPresContext, data->mMedium, + data->mContent)) { data->mStateful = PR_TRUE; return PR_FALSE; // stop iteration } @@ -830,17 +894,18 @@ NS_IMETHODIMP StyleSetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent) { - StatefulData data(aPresContext, aContent); - if (mBackstopSheets) { - mBackstopSheets->EnumerateForwards(SheetHasStatefulStyle, &data); + if (! mRuleProcessors) { + GatherRuleProcessors(); } - if (mDocSheets && (! data.mStateful)) { - mDocSheets->EnumerateForwards(SheetHasStatefulStyle, &data); + if (mRuleProcessors) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + StatefulData data(aPresContext, medium, aContent); + mRuleProcessors->EnumerateForwards(SheetHasStatefulStyle, &data); + NS_IF_RELEASE(medium); + return ((data.mStateful) ? NS_OK : NS_COMFALSE); } - if (mOverrideSheets && (! data.mStateful)) { - mOverrideSheets->EnumerateForwards(SheetHasStatefulStyle, &data); - } - return ((data.mStateful) ? NS_OK : NS_COMFALSE); + return NS_COMFALSE; } diff --git a/mozilla/layout/html/style/public/nsICSSStyleSheet.h b/mozilla/layout/html/style/public/nsICSSStyleSheet.h index 892d5083d47..24664c1e581 100644 --- a/mozilla/layout/html/style/public/nsICSSStyleSheet.h +++ b/mozilla/layout/html/style/public/nsICSSStyleSheet.h @@ -24,6 +24,7 @@ class nsICSSRule; class nsIDOMNode; class nsINameSpace; +class nsICSSStyleRuleProcessor; // IID for the nsICSSStyleSheet interface {8f83b0f0-b21a-11d1-8031-006008159b5a} #define NS_ICSS_STYLE_SHEET_IID \ @@ -62,6 +63,8 @@ public: NS_IMETHOD IsUnmodified(void) const = 0; // NS_OK if not modified since construct/last reset, NS_COMFALSE otherwise NS_IMETHOD SetModified(PRBool aModified) = 0; + + NS_IMETHOD DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor) = 0; }; // XXX for backwards compatibility and convenience diff --git a/mozilla/layout/html/style/src/MANIFEST b/mozilla/layout/html/style/src/MANIFEST index 55595c720c1..8995de8412a 100644 --- a/mozilla/layout/html/style/src/MANIFEST +++ b/mozilla/layout/html/style/src/MANIFEST @@ -4,6 +4,7 @@ nsCSSKeywordList.h nsCSSProps.h nsCSSPropList.h nsCSSValue.h +nsICSSStyleRuleProcessor.h nsICSSRule.h nsICSSGroupRule.h nsICSSStyleRule.h diff --git a/mozilla/layout/html/style/src/Makefile.in b/mozilla/layout/html/style/src/Makefile.in index fa96f98f567..edd6893e7c5 100644 --- a/mozilla/layout/html/style/src/Makefile.in +++ b/mozilla/layout/html/style/src/Makefile.in @@ -57,6 +57,7 @@ EXPORTS = \ nsCSSProps.h \ nsCSSPropList.h \ nsCSSValue.h \ + nsICSSStyleRuleProcessor.h \ nsICSSRule.h \ nsICSSGroupRule.h \ nsICSSStyleRule.h \ diff --git a/mozilla/layout/html/style/src/makefile.win b/mozilla/layout/html/style/src/makefile.win index b89345483f6..b5dfa5abb08 100644 --- a/mozilla/layout/html/style/src/makefile.win +++ b/mozilla/layout/html/style/src/makefile.win @@ -29,6 +29,7 @@ EXPORTS = \ nsCSSProps.h \ nsCSSPropList.h \ nsCSSValue.h \ + nsICSSStyleRuleProcessor.h \ nsICSSRule.h \ nsICSSGroupRule.h \ nsICSSStyleRule.h \ diff --git a/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp b/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp index 82ea400bf22..49bb428c98c 100644 --- a/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp @@ -30,6 +30,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #endif // NECKO #include "nsISupportsArray.h" #include "nsHashtable.h" +#include "nsICSSStyleRuleProcessor.h" #include "nsICSSStyleRule.h" #include "nsICSSNameSpaceRule.h" #include "nsICSSMediaRule.h" @@ -418,6 +419,7 @@ class CSSStyleRuleCollectionImpl; class CSSStyleSheetImpl : public nsICSSStyleSheet, public nsIDOMCSSStyleSheet, + public nsIStyleRuleProcessor, public nsIScriptObjectOwner { public: void* operator new(size_t size); @@ -451,19 +453,26 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); NS_IMETHOD SetOwningNode(nsIDOMNode* aOwningNode); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); + NS_IMETHOD DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // style rule processor API XXX will move to seperate class + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent); NS_IMETHOD ContainsStyleSheet(nsIURI* aURL) const; @@ -1219,6 +1228,21 @@ nsresult CSSStyleSheetImpl::QueryInterface(const nsIID& aIID, return NS_NOINTERFACE; } +NS_IMETHODIMP +CSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor) +{ + aProcessor = this; // XXX temp until rule processing gets factored + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +CSSStyleSheetImpl::DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor) +{ + return NS_OK; +} + static const PRUnichar kNullCh = PRUnichar('\0'); static PRBool ValueIncludes(const nsString& aValueList, const nsString& aValue, PRBool aCaseSensitive) @@ -1585,14 +1609,12 @@ struct ContentEnumData { mContent = aContent; mParentContext = aParentContext; mResults = aResults; - mCount = 0; } nsIPresContext* mPresContext; nsIContent* mContent; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; }; static PRBool SelectorMatchesTree(nsIPresContext* aPresContext, @@ -1662,12 +1684,10 @@ static void ContentEnumFunc(nsICSSStyleRule* aRule, void* aData) nsIStyleRule* iRule; if (NS_OK == aRule->QueryInterface(kIStyleRuleIID, (void**)&iRule)) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); iRule = aRule->GetImportantRule(); if (nsnull != iRule) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); } } @@ -1683,22 +1703,18 @@ static PRBool ContentEnumWrap(nsISupports* aRule, void* aData) } #endif -PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - - nsIAtom* presMedium = nsnull; - - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { ContentEnumData data(aPresContext, aContent, aParentContext, aResults); @@ -1715,7 +1731,6 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } cascade->mRuleHash.EnumerateAllRules(tagAtom, idAtom, classArray, ContentEnumFunc, &data); - matchCount += data.mCount; #ifdef DEBUG_RULES nsISupportsArray* list1; @@ -1735,8 +1750,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_IF_RELEASE(tagAtom); NS_IF_RELEASE(idAtom); } - NS_IF_RELEASE(presMedium); - return matchCount; + return NS_OK; } struct PseudoEnumData { @@ -1749,7 +1763,6 @@ struct PseudoEnumData { mPseudoTag = aPseudoTag; mParentContext = aParentContext; mResults = aResults; - mCount = 0; } nsIPresContext* mPresContext; @@ -1757,7 +1770,6 @@ struct PseudoEnumData { nsIAtom* mPseudoTag; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; }; static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData) @@ -1790,12 +1802,10 @@ static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData) nsIStyleRule* iRule; if (NS_OK == aRule->QueryInterface(kIStyleRuleIID, (void**)&iRule)) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); iRule = aRule->GetImportantRule(); if (nsnull != iRule) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); } } @@ -1810,27 +1820,23 @@ static PRBool PseudoEnumWrap(nsISupports* aRule, void* aData) } #endif -PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aPseudoTag, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - - nsIAtom* presMedium = nsnull; - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aParentContext, aResults); cascade->mRuleHash.EnumerateTagRules(aPseudoTag, PseudoEnumFunc, &data); - matchCount += data.mCount; #ifdef DEBUG_RULES nsISupportsArray* list1; @@ -1846,8 +1852,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_RELEASE(list2); #endif } - NS_IF_RELEASE(presMedium); - return matchCount; + return NS_OK; } struct StateEnumData @@ -1878,21 +1883,18 @@ PRBool StateEnumFunc(void* aSelector, void* aData) // Test if style is dependent on content state NS_IMETHODIMP CSSStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { PRBool isStateful = PR_FALSE; - nsIAtom* presMedium = nsnull; - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { // look up content in state rule list StateEnumData data(aPresContext, aContent); isStateful = (! cascade->mStateSelectors.EnumerateForwards(StateEnumFunc, &data)); // if stopped, have state } - NS_IF_RELEASE(presMedium); return ((isStateful) ? NS_OK : NS_COMFALSE); } @@ -2587,12 +2589,10 @@ GatherStyleRulesForMedium(nsISupports* aRule, void* aData) nsresult CSSStyleSheetImpl::GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules) { - if (aRules) { + if (aRules && (NS_OK == UseForMedium(aMedium))) { CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - if (NS_OK == child->UseForMedium(aMedium)) { - child->GatherRulesFor(aMedium, aRules); - } + child->GatherRulesFor(aMedium, aRules); child = child->mNext; } @@ -2656,13 +2656,11 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) nsresult CSSStyleSheetImpl::SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) { - if (aRules) { + if (aRules && (NS_OK == UseForMedium(aMedium))) { // get child rules first CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - if (NS_OK == child->UseForMedium(aMedium)) { - child->SlowCascadeRulesInto(aMedium, aRules); - } + child->SlowCascadeRulesInto(aMedium, aRules); child = child->mNext; } diff --git a/mozilla/layout/html/style/src/nsHTMLCSSStyleSheet.cpp b/mozilla/layout/html/style/src/nsHTMLCSSStyleSheet.cpp index a33e4f23ca9..ae846ea82b2 100644 --- a/mozilla/layout/html/style/src/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsHTMLCSSStyleSheet.cpp @@ -28,6 +28,7 @@ #include "nsIFrame.h" #include "nsHTMLIIDs.h" #include "nsICSSStyleRule.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleContext.h" #include "nsIPresContext.h" #include "nsIDocument.h" @@ -258,7 +259,8 @@ CSSFirstLetterRule::MapStyleInto(nsIStyleContext* aContext, // ----------------------------------------------------------- -class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet { +class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet, + public nsIStyleRuleProcessor { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); @@ -288,19 +290,26 @@ public: NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const; NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // nsIStyleRuleProcessor api + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); + + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent); // XXX style rule enumerations @@ -410,25 +419,39 @@ nsresult HTMLCSSStyleSheetImpl::QueryInterface(const nsIID& aIID, NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIStyleRuleProcessor::GetIID())) { + *aInstancePtrResult = (void*) ((nsIStyleRuleProcessor*)this); + NS_ADDREF_THIS(); + return NS_OK; + } if (aIID.Equals(kISupportsIID)) { - *aInstancePtrResult = (void*) ((nsISupports*)this); + *aInstancePtrResult = (void*) ((nsISupports*)(nsIStyleSheet*)this); NS_ADDREF_THIS(); return NS_OK; } return NS_NOINTERFACE; } -PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* /*aPrevProcessor*/) +{ + aProcessor = this; + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - nsIStyledContent* styledContent; // just get the one and only style rule from the content's STYLE attribute @@ -440,13 +463,11 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, aResults->Count(&postCount); while (index < postCount) { nsIStyleRule* rule = (nsIStyleRule*)aResults->ElementAt(index++); - matchCount++; nsICSSStyleRule* cssRule; if (NS_SUCCEEDED(rule->QueryInterface(kICSSStyleRuleIID, (void**)&cssRule))) { nsIStyleRule* important = cssRule->GetImportantRule(); if (nsnull != important) { aResults->AppendElement(important); - matchCount++; NS_RELEASE(important); } NS_RELEASE(cssRule); @@ -458,14 +479,16 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_RELEASE(styledContent); } - return matchCount; + return NS_OK; } -PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { if (aPseudoTag == nsHTMLAtoms::firstLinePseudo) { PRUint32 cnt; @@ -479,7 +502,7 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } if (mFirstLineRule) { aResults->AppendElement(mFirstLineRule); - return 1; + return NS_OK; } } } @@ -495,12 +518,12 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } if (mFirstLetterRule) { aResults->AppendElement(mFirstLetterRule); - return 1; + return NS_OK; } } } // else no pseudo frame style... - return 0; + return NS_OK; } NS_IMETHODIMP @@ -522,6 +545,7 @@ HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) // Test if style is dependent on content state NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { return NS_COMFALSE; diff --git a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp index c5c8b39ec57..acd6004591e 100644 --- a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp @@ -32,6 +32,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsHashtable.h" #include "nsIHTMLContent.h" #include "nsIHTMLAttributes.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleRule.h" #include "nsIFrame.h" #include "nsIStyleContext.h" @@ -259,21 +260,25 @@ TableBackgroundRule::MapFontStyleInto(nsIStyleContext* aContext, nsIPresContext* NS_IMETHODIMP TableBackgroundRule::MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext) { - nsStyleColor* styleColor; - styleColor = (nsStyleColor*)aContext->GetMutableStyleData(eStyleStruct_Color); - nsIStyleContext* parentContext = aContext->GetParent(); - const nsStyleColor* parentStyleColor; - parentStyleColor = (const nsStyleColor*)parentContext->GetStyleData(eStyleStruct_Color); - if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) { - styleColor->mBackgroundColor = parentStyleColor->mBackgroundColor; - styleColor->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; - } + if (parentContext) { + nsStyleColor* styleColor; + styleColor = (nsStyleColor*)aContext->GetMutableStyleData(eStyleStruct_Color); - if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE)) { - styleColor->mBackgroundImage = parentStyleColor->mBackgroundImage; - styleColor->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; + const nsStyleColor* parentStyleColor; + parentStyleColor = (const nsStyleColor*)parentContext->GetStyleData(eStyleStruct_Color); + + if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) { + styleColor->mBackgroundColor = parentStyleColor->mBackgroundColor; + styleColor->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; + } + + if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE)) { + styleColor->mBackgroundImage = parentStyleColor->mBackgroundImage; + styleColor->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; + } + NS_RELEASE(parentContext); } return NS_OK; @@ -356,7 +361,8 @@ nsHashKey* AttributeKey::Clone(void) const // ----------------------------------------------------------- -class HTMLStyleSheetImpl : public nsIHTMLStyleSheet { +class HTMLStyleSheetImpl : public nsIHTMLStyleSheet, + public nsIStyleRuleProcessor { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); @@ -385,19 +391,26 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocumemt); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // nsIStyleRuleProcessor API + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); + + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent); // nsIHTMLStyleSheet api NS_IMETHOD Init(nsIURI* aURL, nsIDocument* aDocument); @@ -561,6 +574,11 @@ nsresult HTMLStyleSheetImpl::QueryInterface(const nsIID& aIID, NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIStyleRuleProcessor::GetIID())) { + *aInstancePtrResult = (void*) ((nsIStyleRuleProcessor*)this); + NS_ADDREF_THIS(); + return NS_OK; + } if (aIID.Equals(kIStyleFrameConstructionIID)) { // XXX this breaks XPCOM rules since it isn't a proper delegate // This is a temporary method of connecting the constructor for now @@ -583,17 +601,26 @@ nsresult HTMLStyleSheetImpl::QueryInterface(const nsIID& aIID, return NS_NOINTERFACE; } -PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* /*aPrevProcessor*/) +{ + aProcessor = this; + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - nsIStyledContent* styledContent; if (NS_SUCCEEDED(aContent->QueryInterface(nsIStyledContent::GetIID(), (void**)&styledContent))) { PRInt32 nameSpace; @@ -616,7 +643,6 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (! linkHandler) { if (nsnull != mLinkRule) { aResults->AppendElement(mLinkRule); - matchCount++; } } else { @@ -647,13 +673,11 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, case eLinkState_Unvisited: if (nsnull != mLinkRule) { aResults->AppendElement(mLinkRule); - matchCount++; } break; case eLinkState_Visited: if (nsnull != mVisitedRule) { aResults->AppendElement(mVisitedRule); - matchCount++; } break; default: @@ -676,7 +700,6 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (NS_OK == eventStateManager->GetContentState(aContent, state)) { if (0 != (state & NS_EVENT_STATE_ACTIVE)) { aResults->AppendElement(mActiveRule); - matchCount++; } } NS_RELEASE(eventStateManager); @@ -695,38 +718,31 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (eCompatibility_NavQuirks == mode) { if (mDocumentColorRule) { aResults->AppendElement(mDocumentColorRule); - matchCount++; } aResults->AppendElement(mTableBackgroundRule); - matchCount++; } } else if (tag == nsHTMLAtoms::html) { if (mDocumentColorRule) { aResults->AppendElement(mDocumentColorRule); - matchCount++; } } NS_IF_RELEASE(tag); } // end html namespace - // just get the one and only style rule from the content - PRUint32 preCount = 0; - PRUint32 postCount = 0; - aResults->Count(&preCount); + // just get the style rules from the content styledContent->GetContentStyleRules(aResults); - aResults->Count(&postCount); - matchCount += (postCount - preCount); NS_RELEASE(styledContent); } - return matchCount; + return NS_OK; } // Test if style is dependent on content state NS_IMETHODIMP HTMLStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { nsresult result = NS_COMFALSE; @@ -757,14 +773,16 @@ HTMLStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, -PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { // no pseudo frame style - return 0; + return NS_OK; } diff --git a/mozilla/layout/html/style/src/nsICSSStyleRuleProcessor.h b/mozilla/layout/html/style/src/nsICSSStyleRuleProcessor.h new file mode 100644 index 00000000000..29b88c1705e --- /dev/null +++ b/mozilla/layout/html/style/src/nsICSSStyleRuleProcessor.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsICSSStyleRuleProcessor_h___ +#define nsICSSStyleRuleProcessor_h___ + +#include "nslayout.h" +#include "nsIStyleRuleProcessor.h" + +class nsICSSStyleSheet; + +// IID for the nsICSSStyleRuleProcessor interface {98bf169c-7b7c-11d3-ba05-001083023c2b} +#define NS_ICSS_STYLE_RULE_PROCESSOR_IID \ +{0x98bf169c, 0x7b7c, 0x11d3, {0xba, 0x05, 0x00, 0x10, 0x83, 0x02, 0x3c, 0x2b}} + +/* The CSS style rule processor provides a mechanism for sibling style sheets + * to combine their rule processing in order to allow proper cascading to happen. + * + * When queried for a rule processor, a CSS style sheet will append itself to + * the previous CSS processor if present, and return nsnull. Otherwise it will + * create a new processor for itself. + * + * CSS style rule processors keep a live reference on all style sheets bound to them + * The CSS style sheets keep a weak reference on all the processors that they are + * bound to (many to many). The CSS style sheet is told when the rule processor is + * going away (via DropRuleProcessorReference). + */ +class nsICSSStyleRuleProcessor: public nsIStyleRuleProcessor { +public: + static const nsIID& GetIID() { static nsIID iid = NS_ICSS_STYLE_RULE_PROCESSOR_IID; return iid; } + + NS_IMETHOD AppendStyleSheet(nsICSSStyleSheet* aStyleSheet) = 0; +}; + +#endif /* nsICSSStyleRuleProcessor_h___ */ diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index 82ea400bf22..49bb428c98c 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -30,6 +30,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #endif // NECKO #include "nsISupportsArray.h" #include "nsHashtable.h" +#include "nsICSSStyleRuleProcessor.h" #include "nsICSSStyleRule.h" #include "nsICSSNameSpaceRule.h" #include "nsICSSMediaRule.h" @@ -418,6 +419,7 @@ class CSSStyleRuleCollectionImpl; class CSSStyleSheetImpl : public nsICSSStyleSheet, public nsIDOMCSSStyleSheet, + public nsIStyleRuleProcessor, public nsIScriptObjectOwner { public: void* operator new(size_t size); @@ -451,19 +453,26 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); NS_IMETHOD SetOwningNode(nsIDOMNode* aOwningNode); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); + NS_IMETHOD DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // style rule processor API XXX will move to seperate class + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent); NS_IMETHOD ContainsStyleSheet(nsIURI* aURL) const; @@ -1219,6 +1228,21 @@ nsresult CSSStyleSheetImpl::QueryInterface(const nsIID& aIID, return NS_NOINTERFACE; } +NS_IMETHODIMP +CSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor) +{ + aProcessor = this; // XXX temp until rule processing gets factored + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +CSSStyleSheetImpl::DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor) +{ + return NS_OK; +} + static const PRUnichar kNullCh = PRUnichar('\0'); static PRBool ValueIncludes(const nsString& aValueList, const nsString& aValue, PRBool aCaseSensitive) @@ -1585,14 +1609,12 @@ struct ContentEnumData { mContent = aContent; mParentContext = aParentContext; mResults = aResults; - mCount = 0; } nsIPresContext* mPresContext; nsIContent* mContent; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; }; static PRBool SelectorMatchesTree(nsIPresContext* aPresContext, @@ -1662,12 +1684,10 @@ static void ContentEnumFunc(nsICSSStyleRule* aRule, void* aData) nsIStyleRule* iRule; if (NS_OK == aRule->QueryInterface(kIStyleRuleIID, (void**)&iRule)) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); iRule = aRule->GetImportantRule(); if (nsnull != iRule) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); } } @@ -1683,22 +1703,18 @@ static PRBool ContentEnumWrap(nsISupports* aRule, void* aData) } #endif -PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - - nsIAtom* presMedium = nsnull; - - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { ContentEnumData data(aPresContext, aContent, aParentContext, aResults); @@ -1715,7 +1731,6 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } cascade->mRuleHash.EnumerateAllRules(tagAtom, idAtom, classArray, ContentEnumFunc, &data); - matchCount += data.mCount; #ifdef DEBUG_RULES nsISupportsArray* list1; @@ -1735,8 +1750,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_IF_RELEASE(tagAtom); NS_IF_RELEASE(idAtom); } - NS_IF_RELEASE(presMedium); - return matchCount; + return NS_OK; } struct PseudoEnumData { @@ -1749,7 +1763,6 @@ struct PseudoEnumData { mPseudoTag = aPseudoTag; mParentContext = aParentContext; mResults = aResults; - mCount = 0; } nsIPresContext* mPresContext; @@ -1757,7 +1770,6 @@ struct PseudoEnumData { nsIAtom* mPseudoTag; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; }; static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData) @@ -1790,12 +1802,10 @@ static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData) nsIStyleRule* iRule; if (NS_OK == aRule->QueryInterface(kIStyleRuleIID, (void**)&iRule)) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); iRule = aRule->GetImportantRule(); if (nsnull != iRule) { data->mResults->AppendElement(iRule); - data->mCount++; NS_RELEASE(iRule); } } @@ -1810,27 +1820,23 @@ static PRBool PseudoEnumWrap(nsISupports* aRule, void* aData) } #endif -PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aPseudoTag, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - - nsIAtom* presMedium = nsnull; - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aParentContext, aResults); cascade->mRuleHash.EnumerateTagRules(aPseudoTag, PseudoEnumFunc, &data); - matchCount += data.mCount; #ifdef DEBUG_RULES nsISupportsArray* list1; @@ -1846,8 +1852,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_RELEASE(list2); #endif } - NS_IF_RELEASE(presMedium); - return matchCount; + return NS_OK; } struct StateEnumData @@ -1878,21 +1883,18 @@ PRBool StateEnumFunc(void* aSelector, void* aData) // Test if style is dependent on content state NS_IMETHODIMP CSSStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { PRBool isStateful = PR_FALSE; - nsIAtom* presMedium = nsnull; - aPresContext->GetMedium(&presMedium); - - RuleCascadeData* cascade = GetRuleCascade(presMedium); + RuleCascadeData* cascade = GetRuleCascade(aMedium); if (cascade) { // look up content in state rule list StateEnumData data(aPresContext, aContent); isStateful = (! cascade->mStateSelectors.EnumerateForwards(StateEnumFunc, &data)); // if stopped, have state } - NS_IF_RELEASE(presMedium); return ((isStateful) ? NS_OK : NS_COMFALSE); } @@ -2587,12 +2589,10 @@ GatherStyleRulesForMedium(nsISupports* aRule, void* aData) nsresult CSSStyleSheetImpl::GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules) { - if (aRules) { + if (aRules && (NS_OK == UseForMedium(aMedium))) { CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - if (NS_OK == child->UseForMedium(aMedium)) { - child->GatherRulesFor(aMedium, aRules); - } + child->GatherRulesFor(aMedium, aRules); child = child->mNext; } @@ -2656,13 +2656,11 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) nsresult CSSStyleSheetImpl::SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) { - if (aRules) { + if (aRules && (NS_OK == UseForMedium(aMedium))) { // get child rules first CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - if (NS_OK == child->UseForMedium(aMedium)) { - child->SlowCascadeRulesInto(aMedium, aRules); - } + child->SlowCascadeRulesInto(aMedium, aRules); child = child->mNext; } diff --git a/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp b/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp index a33e4f23ca9..ae846ea82b2 100644 --- a/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp @@ -28,6 +28,7 @@ #include "nsIFrame.h" #include "nsHTMLIIDs.h" #include "nsICSSStyleRule.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleContext.h" #include "nsIPresContext.h" #include "nsIDocument.h" @@ -258,7 +259,8 @@ CSSFirstLetterRule::MapStyleInto(nsIStyleContext* aContext, // ----------------------------------------------------------- -class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet { +class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet, + public nsIStyleRuleProcessor { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); @@ -288,19 +290,26 @@ public: NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const; NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // nsIStyleRuleProcessor api + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); + + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent); // XXX style rule enumerations @@ -410,25 +419,39 @@ nsresult HTMLCSSStyleSheetImpl::QueryInterface(const nsIID& aIID, NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIStyleRuleProcessor::GetIID())) { + *aInstancePtrResult = (void*) ((nsIStyleRuleProcessor*)this); + NS_ADDREF_THIS(); + return NS_OK; + } if (aIID.Equals(kISupportsIID)) { - *aInstancePtrResult = (void*) ((nsISupports*)this); + *aInstancePtrResult = (void*) ((nsISupports*)(nsIStyleSheet*)this); NS_ADDREF_THIS(); return NS_OK; } return NS_NOINTERFACE; } -PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* /*aPrevProcessor*/) +{ + aProcessor = this; + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - nsIStyledContent* styledContent; // just get the one and only style rule from the content's STYLE attribute @@ -440,13 +463,11 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, aResults->Count(&postCount); while (index < postCount) { nsIStyleRule* rule = (nsIStyleRule*)aResults->ElementAt(index++); - matchCount++; nsICSSStyleRule* cssRule; if (NS_SUCCEEDED(rule->QueryInterface(kICSSStyleRuleIID, (void**)&cssRule))) { nsIStyleRule* important = cssRule->GetImportantRule(); if (nsnull != important) { aResults->AppendElement(important); - matchCount++; NS_RELEASE(important); } NS_RELEASE(cssRule); @@ -458,14 +479,16 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, NS_RELEASE(styledContent); } - return matchCount; + return NS_OK; } -PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { if (aPseudoTag == nsHTMLAtoms::firstLinePseudo) { PRUint32 cnt; @@ -479,7 +502,7 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } if (mFirstLineRule) { aResults->AppendElement(mFirstLineRule); - return 1; + return NS_OK; } } } @@ -495,12 +518,12 @@ PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, } if (mFirstLetterRule) { aResults->AppendElement(mFirstLetterRule); - return 1; + return NS_OK; } } } // else no pseudo frame style... - return 0; + return NS_OK; } NS_IMETHODIMP @@ -522,6 +545,7 @@ HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) // Test if style is dependent on content state NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { return NS_COMFALSE; diff --git a/mozilla/layout/style/nsHTMLStyleSheet.cpp b/mozilla/layout/style/nsHTMLStyleSheet.cpp index c5c8b39ec57..acd6004591e 100644 --- a/mozilla/layout/style/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLStyleSheet.cpp @@ -32,6 +32,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsHashtable.h" #include "nsIHTMLContent.h" #include "nsIHTMLAttributes.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleRule.h" #include "nsIFrame.h" #include "nsIStyleContext.h" @@ -259,21 +260,25 @@ TableBackgroundRule::MapFontStyleInto(nsIStyleContext* aContext, nsIPresContext* NS_IMETHODIMP TableBackgroundRule::MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext) { - nsStyleColor* styleColor; - styleColor = (nsStyleColor*)aContext->GetMutableStyleData(eStyleStruct_Color); - nsIStyleContext* parentContext = aContext->GetParent(); - const nsStyleColor* parentStyleColor; - parentStyleColor = (const nsStyleColor*)parentContext->GetStyleData(eStyleStruct_Color); - if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) { - styleColor->mBackgroundColor = parentStyleColor->mBackgroundColor; - styleColor->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; - } + if (parentContext) { + nsStyleColor* styleColor; + styleColor = (nsStyleColor*)aContext->GetMutableStyleData(eStyleStruct_Color); - if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE)) { - styleColor->mBackgroundImage = parentStyleColor->mBackgroundImage; - styleColor->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; + const nsStyleColor* parentStyleColor; + parentStyleColor = (const nsStyleColor*)parentContext->GetStyleData(eStyleStruct_Color); + + if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) { + styleColor->mBackgroundColor = parentStyleColor->mBackgroundColor; + styleColor->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; + } + + if (!(parentStyleColor->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE)) { + styleColor->mBackgroundImage = parentStyleColor->mBackgroundImage; + styleColor->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; + } + NS_RELEASE(parentContext); } return NS_OK; @@ -356,7 +361,8 @@ nsHashKey* AttributeKey::Clone(void) const // ----------------------------------------------------------- -class HTMLStyleSheetImpl : public nsIHTMLStyleSheet { +class HTMLStyleSheetImpl : public nsIHTMLStyleSheet, + public nsIStyleRuleProcessor { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); @@ -385,19 +391,26 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocumemt); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor); - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults); + // nsIStyleRuleProcessor API + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent); + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults); + + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent); // nsIHTMLStyleSheet api NS_IMETHOD Init(nsIURI* aURL, nsIDocument* aDocument); @@ -561,6 +574,11 @@ nsresult HTMLStyleSheetImpl::QueryInterface(const nsIID& aIID, NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(nsIStyleRuleProcessor::GetIID())) { + *aInstancePtrResult = (void*) ((nsIStyleRuleProcessor*)this); + NS_ADDREF_THIS(); + return NS_OK; + } if (aIID.Equals(kIStyleFrameConstructionIID)) { // XXX this breaks XPCOM rules since it isn't a proper delegate // This is a temporary method of connecting the constructor for now @@ -583,17 +601,26 @@ nsresult HTMLStyleSheetImpl::QueryInterface(const nsIID& aIID, return NS_NOINTERFACE; } -PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* /*aPrevProcessor*/) +{ + aProcessor = this; + NS_ADDREF(aProcessor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); - PRInt32 matchCount = 0; - nsIStyledContent* styledContent; if (NS_SUCCEEDED(aContent->QueryInterface(nsIStyledContent::GetIID(), (void**)&styledContent))) { PRInt32 nameSpace; @@ -616,7 +643,6 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (! linkHandler) { if (nsnull != mLinkRule) { aResults->AppendElement(mLinkRule); - matchCount++; } } else { @@ -647,13 +673,11 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, case eLinkState_Unvisited: if (nsnull != mLinkRule) { aResults->AppendElement(mLinkRule); - matchCount++; } break; case eLinkState_Visited: if (nsnull != mVisitedRule) { aResults->AppendElement(mVisitedRule); - matchCount++; } break; default: @@ -676,7 +700,6 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (NS_OK == eventStateManager->GetContentState(aContent, state)) { if (0 != (state & NS_EVENT_STATE_ACTIVE)) { aResults->AppendElement(mActiveRule); - matchCount++; } } NS_RELEASE(eventStateManager); @@ -695,38 +718,31 @@ PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, if (eCompatibility_NavQuirks == mode) { if (mDocumentColorRule) { aResults->AppendElement(mDocumentColorRule); - matchCount++; } aResults->AppendElement(mTableBackgroundRule); - matchCount++; } } else if (tag == nsHTMLAtoms::html) { if (mDocumentColorRule) { aResults->AppendElement(mDocumentColorRule); - matchCount++; } } NS_IF_RELEASE(tag); } // end html namespace - // just get the one and only style rule from the content - PRUint32 preCount = 0; - PRUint32 postCount = 0; - aResults->Count(&preCount); + // just get the style rules from the content styledContent->GetContentStyleRules(aResults); - aResults->Count(&postCount); - matchCount += (postCount - preCount); NS_RELEASE(styledContent); } - return matchCount; + return NS_OK; } // Test if style is dependent on content state NS_IMETHODIMP HTMLStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, nsIContent* aContent) { nsresult result = NS_COMFALSE; @@ -757,14 +773,16 @@ HTMLStyleSheetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, -PRInt32 HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) +NS_IMETHODIMP +HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) { // no pseudo frame style - return 0; + return NS_OK; } diff --git a/mozilla/layout/style/nsICSSStyleSheet.h b/mozilla/layout/style/nsICSSStyleSheet.h index 892d5083d47..24664c1e581 100644 --- a/mozilla/layout/style/nsICSSStyleSheet.h +++ b/mozilla/layout/style/nsICSSStyleSheet.h @@ -24,6 +24,7 @@ class nsICSSRule; class nsIDOMNode; class nsINameSpace; +class nsICSSStyleRuleProcessor; // IID for the nsICSSStyleSheet interface {8f83b0f0-b21a-11d1-8031-006008159b5a} #define NS_ICSS_STYLE_SHEET_IID \ @@ -62,6 +63,8 @@ public: NS_IMETHOD IsUnmodified(void) const = 0; // NS_OK if not modified since construct/last reset, NS_COMFALSE otherwise NS_IMETHOD SetModified(PRBool aModified) = 0; + + NS_IMETHOD DropRuleProcessorReference(nsICSSStyleRuleProcessor* aProcessor) = 0; }; // XXX for backwards compatibility and convenience diff --git a/mozilla/layout/style/nsIStyleRuleProcessor.h b/mozilla/layout/style/nsIStyleRuleProcessor.h new file mode 100644 index 00000000000..ff317a9445a --- /dev/null +++ b/mozilla/layout/style/nsIStyleRuleProcessor.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsIStyleRuleProcessor_h___ +#define nsIStyleRuleProcessor_h___ + +#include + +#include "nslayout.h" +#include "nsISupports.h" + +class nsIStyleSheet; +class nsIStyleContext; +class nsIPresContext; +class nsIContent; +class nsISupportsArray; +class nsIAtom; + +// IID for the nsIStyleRuleProcessor interface {015575fe-7b6c-11d3-ba05-001083023c2b} +#define NS_ISTYLE_RULE_PROCESSOR_IID \ +{0x015575fe, 0x7b6c, 0x11d3, {0xba, 0x05, 0x00, 0x10, 0x83, 0x02, 0x3c, 0x2b}} + +/* The style rule processor interface is a mechanism to seperate the matching + * of style rules from style sheet instances. + * Simple style sheets can and will act as their own processor. + * Sheets where rule ordering interlaces between multiple sheets, will need to + * share a single rule processor between them (CSS sheets do this for cascading order) + */ +class nsIStyleRuleProcessor : public nsISupports { +public: + static const nsIID& GetIID() { static nsIID iid = NS_ISTYLE_RULE_PROCESSOR_IID; return iid; } + + // populate supports array with nsIStyleRule* + // rules are ordered, those with higher precedence come last + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) = 0; + + NS_IMETHOD RulesMatching(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aParentContent, + nsIAtom* aPseudoTag, + nsIStyleContext* aParentContext, + nsISupportsArray* aResults) = 0; + + // Test if style is dependent on content state + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, + nsIAtom* aMedium, + nsIContent* aContent) = 0; +}; + +#endif /* nsIStyleRuleProcessor_h___ */ diff --git a/mozilla/layout/style/nsIStyleSheet.h b/mozilla/layout/style/nsIStyleSheet.h index 1a630e76698..dcbf8be9305 100644 --- a/mozilla/layout/style/nsIStyleSheet.h +++ b/mozilla/layout/style/nsIStyleSheet.h @@ -29,6 +29,7 @@ class nsIPresContext; class nsIContent; class nsIDocument; class nsIStyleContext; +class nsIStyleRuleProcessor; // IID for the nsIStyleSheet interface {8c4a80a0-ad6a-11d1-8031-006008159b5a} #define NS_ISTYLE_SHEET_IID \ @@ -54,22 +55,9 @@ public: NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const = 0; // may be null NS_IMETHOD SetOwningDocument(nsIDocument* aDocument) = 0; - // populate supports array with nsIStyleRule* - // rules are ordered, those with higher precedence come last - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) = 0; - - virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsIStyleContext* aParentContext, - nsISupportsArray* aResults) = 0; - - // Test if style is dependent on content state - NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, - nsIContent* aContent) = 0; + // style rule processor access + NS_IMETHOD GetStyleRuleProcessor(nsIStyleRuleProcessor*& aProcessor, + nsIStyleRuleProcessor* aPrevProcessor) = 0; // XXX style rule enumerations diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index 0fa87d6d040..69a94c90558 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -18,6 +18,7 @@ #include "nsCOMPtr.h" #include "nsIStyleSet.h" #include "nsIStyleSheet.h" +#include "nsIStyleRuleProcessor.h" #include "nsIStyleRule.h" #include "nsIStyleContext.h" #include "nsISupportsArray.h" @@ -174,15 +175,22 @@ private: protected: virtual ~StyleSetImpl(); PRBool EnsureArray(nsISupportsArray** aArray); + void RecycleArray(nsISupportsArray** aArray); + void ClearRuleProcessors(void); + nsresult GatherRuleProcessors(void); + nsIStyleContext* GetContext(nsIPresContext* aPresContext, nsIStyleContext* aParentContext, nsIAtom* aPseudoTag, nsISupportsArray* aRules, PRBool aForceUnique, PRBool& aUsedRules); void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets); void ListContexts(nsIStyleContext* aRootContext, FILE* out, PRInt32 aIndent); - nsISupportsArray* mOverrideSheets; - nsISupportsArray* mDocSheets; - nsISupportsArray* mBackstopSheets; + nsISupportsArray* mOverrideSheets; // most significant first + nsISupportsArray* mDocSheets; // " " + nsISupportsArray* mBackstopSheets; // " " + + nsISupportsArray* mRuleProcessors; // least significant first + nsISupportsArray* mRecycler; nsIStyleFrameConstruction* mFrameConstructor; @@ -198,6 +206,7 @@ StyleSetImpl::StyleSetImpl() : mOverrideSheets(nsnull), mDocSheets(nsnull), mBackstopSheets(nsnull), + mRuleProcessors(nsnull), mRecycler(nsnull), mFrameConstructor(nsnull) { @@ -211,6 +220,7 @@ StyleSetImpl::~StyleSetImpl() NS_IF_RELEASE(mOverrideSheets); NS_IF_RELEASE(mDocSheets); NS_IF_RELEASE(mBackstopSheets); + NS_IF_RELEASE(mRuleProcessors); NS_IF_RELEASE(mFrameConstructor); NS_IF_RELEASE(mRecycler); } @@ -224,13 +234,94 @@ NS_IMPL_ISUPPORTS2(StyleSetImpl, nsIStyleSet, nsITimeRecorder) PRBool StyleSetImpl::EnsureArray(nsISupportsArray** aArray) { if (nsnull == *aArray) { - if (NS_OK != NS_NewISupportsArray(aArray)) { - return PR_FALSE; + (*aArray) = mRecycler; + mRecycler = nsnull; + if (nsnull == *aArray) { + if (NS_OK != NS_NewISupportsArray(aArray)) { + return PR_FALSE; + } } } return PR_TRUE; } +void +StyleSetImpl::RecycleArray(nsISupportsArray** aArray) +{ + if (! mRecycler) { + mRecycler = *aArray; // take ref + mRecycler->Clear(); + *aArray = nsnull; + } + else { // already have a recycled array + NS_RELEASE(*aArray); + } +} + +void +StyleSetImpl::ClearRuleProcessors(void) +{ + if (mRuleProcessors) { + RecycleArray(&mRuleProcessors); + } +} + +struct RuleProcessorData { + RuleProcessorData(nsISupportsArray* aRuleProcessors) + : mRuleProcessors(aRuleProcessors), + mPrevProcessor(nsnull) + {} + + nsISupportsArray* mRuleProcessors; + nsIStyleRuleProcessor* mPrevProcessor; +}; + +static PRBool +EnumRuleProcessor(nsISupports* aSheet, void* aData) +{ + nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + RuleProcessorData* data = (RuleProcessorData*)aData; + + nsIStyleRuleProcessor* processor = nsnull; + nsresult result = sheet->GetStyleRuleProcessor(processor, data->mPrevProcessor); + if (NS_SUCCEEDED(result) && processor) { + if (processor != data->mPrevProcessor) { + data->mRuleProcessors->AppendElement(processor); + data->mPrevProcessor = processor; // ref is held by array + } + NS_RELEASE(processor); + } + return PR_TRUE; +} + +nsresult +StyleSetImpl::GatherRuleProcessors(void) +{ + nsresult result = NS_ERROR_OUT_OF_MEMORY; + if (EnsureArray(&mRuleProcessors)) { + RuleProcessorData data(mRuleProcessors); + if (mBackstopSheets) { + mBackstopSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + if (mDocSheets) { + data.mPrevProcessor = nsnull; + mDocSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + if (mOverrideSheets) { + data.mPrevProcessor = nsnull; + mOverrideSheets->EnumerateBackwards(EnumRuleProcessor, &data); + } + result = NS_OK; + PRUint32 count; + mRuleProcessors->Count(&count); + if (0 == count) { + RecycleArray(&mRuleProcessors); + } + } + return result; +} + + // ----- Override sheets void StyleSetImpl::AppendOverrideStyleSheet(nsIStyleSheet* aSheet) @@ -239,6 +330,7 @@ void StyleSetImpl::AppendOverrideStyleSheet(nsIStyleSheet* aSheet) if (EnsureArray(&mOverrideSheets)) { mOverrideSheets->RemoveElement(aSheet); mOverrideSheets->AppendElement(aSheet); + ClearRuleProcessors(); } } @@ -250,6 +342,7 @@ void StyleSetImpl::InsertOverrideStyleSheetAfter(nsIStyleSheet* aSheet, mOverrideSheets->RemoveElement(aSheet); PRInt32 index = mOverrideSheets->IndexOf(aAfterSheet); mOverrideSheets->InsertElementAt(aSheet, ++index); + ClearRuleProcessors(); } } @@ -261,6 +354,7 @@ void StyleSetImpl::InsertOverrideStyleSheetBefore(nsIStyleSheet* aSheet, mOverrideSheets->RemoveElement(aSheet); PRInt32 index = mOverrideSheets->IndexOf(aBeforeSheet); mOverrideSheets->InsertElementAt(aSheet, ((-1 < index) ? index : 0)); + ClearRuleProcessors(); } } @@ -270,6 +364,7 @@ void StyleSetImpl::RemoveOverrideStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mOverrideSheets) { mOverrideSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -325,6 +420,7 @@ void StyleSetImpl::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocumen if (nsnull == mFrameConstructor) { aSheet->QueryInterface(kIStyleFrameConstructionIID, (void **)&mFrameConstructor); } + ClearRuleProcessors(); } } @@ -334,6 +430,7 @@ void StyleSetImpl::RemoveDocStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mDocSheets) { mDocSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -365,6 +462,7 @@ void StyleSetImpl::AppendBackstopStyleSheet(nsIStyleSheet* aSheet) if (EnsureArray(&mBackstopSheets)) { mBackstopSheets->RemoveElement(aSheet); mBackstopSheets->AppendElement(aSheet); + ClearRuleProcessors(); } } @@ -376,6 +474,7 @@ void StyleSetImpl::InsertBackstopStyleSheetAfter(nsIStyleSheet* aSheet, mBackstopSheets->RemoveElement(aSheet); PRInt32 index = mBackstopSheets->IndexOf(aAfterSheet); mBackstopSheets->InsertElementAt(aSheet, ++index); + ClearRuleProcessors(); } } @@ -387,6 +486,7 @@ void StyleSetImpl::InsertBackstopStyleSheetBefore(nsIStyleSheet* aSheet, mBackstopSheets->RemoveElement(aSheet); PRInt32 index = mBackstopSheets->IndexOf(aBeforeSheet); mBackstopSheets->InsertElementAt(aSheet, ((-1 < index) ? index : 0)); + ClearRuleProcessors(); } } @@ -396,6 +496,7 @@ void StyleSetImpl::RemoveBackstopStyleSheet(nsIStyleSheet* aSheet) if (nsnull != mBackstopSheets) { mBackstopSheets->RemoveElement(aSheet); + ClearRuleProcessors(); } } @@ -429,8 +530,7 @@ struct RulesMatchingData { mMedium(aMedium), mContent(aContent), mParentContext(aParentContext), - mResults(aResults), - mCount(0) + mResults(aResults) { } nsIPresContext* mPresContext; @@ -438,20 +538,16 @@ struct RulesMatchingData { nsIContent* mContent; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; - }; static PRBool -EnumRulesMatching(nsISupports* aSheet, void* aData) +EnumRulesMatching(nsISupports* aProcessor, void* aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; RulesMatchingData* data = (RulesMatchingData*)aData; - if (NS_OK == sheet->UseForMedium(data->mMedium)) { - data->mCount += sheet->RulesMatching(data->mPresContext, data->mContent, - data->mParentContext, data->mResults); - } + processor->RulesMatching(data->mPresContext, data->mMedium, data->mContent, + data->mParentContext, data->mResults); return PR_TRUE; } @@ -483,7 +579,7 @@ nsIStyleContext* StyleSetImpl::GetContext(nsIPresContext* aPresContext, } // XXX for now only works for strength 0 & 1 -static void SortRulesByStrength(nsISupportsArray* aRules, PRInt32& aBackstopRuleCount) +static void SortRulesByStrength(nsISupportsArray* aRules) { PRUint32 cnt; nsresult rv = aRules->Count(&cnt); @@ -500,9 +596,6 @@ static void SortRulesByStrength(nsISupportsArray* aRules, PRInt32& aBackstopRule aRules->RemoveElementAt(index); aRules->AppendElement(rule); count--; - if (index < aBackstopRuleCount) { - aBackstopRuleCount--; - } } else { index++; @@ -534,47 +627,39 @@ nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext, NS_ASSERTION(aPresContext, "must have pres context"); if (aContent && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + RulesMatchingData data(aPresContext, medium, aContent, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - RulesMatchingData data(aPresContext, medium, aContent, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, nsnull, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount = 0; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, nsnull, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); + result = GetContext(aPresContext, aParentContext, nsnull, nsnull, aForceUnique, usedRules); } + NS_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - result = GetContext(aPresContext, aParentContext, nsnull, nsnull, aForceUnique, usedRules); - } - NS_RELEASE(medium); } } @@ -594,8 +679,7 @@ struct PseudoRulesMatchingData { mParentContent(aParentContent), mPseudoTag(aPseudoTag), mParentContext(aParentContext), - mResults(aResults), - mCount(0) + mResults(aResults) { } nsIPresContext* mPresContext; @@ -604,21 +688,17 @@ struct PseudoRulesMatchingData { nsIAtom* mPseudoTag; nsIStyleContext* mParentContext; nsISupportsArray* mResults; - PRInt32 mCount; - }; static PRBool -EnumPseudoRulesMatching(nsISupports* aSheet, void* aData) +EnumPseudoRulesMatching(nsISupports* aProcessor, void* aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aSheet; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; PseudoRulesMatchingData* data = (PseudoRulesMatchingData*)aData; - if (NS_OK == sheet->UseForMedium(data->mMedium)) { - data->mCount += sheet->RulesMatching(data->mPresContext, data->mParentContent, - data->mPseudoTag, - data->mParentContext, data->mResults); - } + processor->RulesMatching(data->mPresContext, data->mMedium, + data->mParentContent, data->mPseudoTag, + data->mParentContext, data->mResults); return PR_TRUE; } @@ -635,48 +715,41 @@ nsIStyleContext* StyleSetImpl::ResolvePseudoStyleFor(nsIPresContext* aPresContex NS_ASSERTION(aPresContext, "must have pres context"); if (aPseudoTag && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + PseudoRulesMatchingData data(aPresContext, medium, aParentContent, + aPseudoTag, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumPseudoRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - PseudoRulesMatchingData data(aPresContext, medium, aParentContent, - aPseudoTag, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount = 0; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + rules->Clear(); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, nsnull, aForceUnique, usedRules); } + NS_IF_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - result = GetContext(aPresContext, aParentContext, aPseudoTag, nsnull, aForceUnique, usedRules); - } - NS_IF_RELEASE(medium); } } @@ -697,47 +770,40 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, NS_ASSERTION(aPresContext, "must have pres context"); if (aPseudoTag && aPresContext) { - nsISupportsArray* rules = mRecycler; - mRecycler = nsnull; - if (nsnull == rules) { - NS_NewISupportsArray(&rules); + if (! mRuleProcessors) { + GatherRuleProcessors(); } + if (mRuleProcessors) { + nsISupportsArray* rules = nsnull; + if (EnsureArray(&rules)) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + PseudoRulesMatchingData data(aPresContext, medium, aParentContent, + aPseudoTag, aParentContext, rules); + mRuleProcessors->EnumerateForwards(EnumPseudoRulesMatching, &data); - if (nsnull != rules) { - nsIAtom* medium = nsnull; - aPresContext->GetMedium(&medium); - PseudoRulesMatchingData data(aPresContext, medium, aParentContent, - aPseudoTag, aParentContext, rules); - if (mBackstopSheets) { - mBackstopSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - PRInt32 backstopRules = data.mCount; - if (mDocSheets) { - mDocSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - if (mOverrideSheets) { - mOverrideSheets->EnumerateBackwards(EnumPseudoRulesMatching, &data); - } - - PRBool usedRules = PR_FALSE; - if (0 < data.mCount) { - SortRulesByStrength(rules, backstopRules); - result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); - if (usedRules) { - NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); - NS_RELEASE(rules); + PRBool usedRules = PR_FALSE; + PRUint32 ruleCount; + rules->Count(&ruleCount); + if (0 < ruleCount) { + SortRulesByStrength(rules); + result = GetContext(aPresContext, aParentContext, aPseudoTag, rules, aForceUnique, usedRules); + if (usedRules) { + NS_ASSERT_REFCOUNT(rules, 2, "rules array was used elsewhere"); + NS_RELEASE(rules); + } + else { + NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); + rules->Clear(); + RecycleArray(&rules); + } } else { NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - rules->Clear(); - mRecycler = rules; + RecycleArray(&rules); } + NS_IF_RELEASE(medium); } - else { - NS_ASSERT_REFCOUNT(rules, 1, "rules array was used elsewhere"); - mRecycler = rules; - } - NS_IF_RELEASE(medium); } } @@ -780,12 +846,7 @@ StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, else { // need to make one in the new parent nsISupportsArray* newRules = nsnull; if (rules) { - newRules = mRecycler; - mRecycler = nsnull; - if (! newRules) { - result = NS_NewISupportsArray(&newRules); - } - if (newRules) { + if (EnsureArray(&newRules)) { newRules->AppendElements(rules); } } @@ -804,21 +865,24 @@ StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, } struct StatefulData { - StatefulData(nsIPresContext* aPresContext, nsIContent* aContent) + StatefulData(nsIPresContext* aPresContext, nsIAtom* aMedium, nsIContent* aContent) : mPresContext(aPresContext), + mMedium(aMedium), mContent(aContent), mStateful(PR_FALSE) {} nsIPresContext* mPresContext; + nsIAtom* mMedium; nsIContent* mContent; PRBool mStateful; }; -static PRBool SheetHasStatefulStyle(nsISupports* aElement, void *aData) +static PRBool SheetHasStatefulStyle(nsISupports* aProcessor, void *aData) { - nsIStyleSheet* sheet = (nsIStyleSheet*)aElement; + nsIStyleRuleProcessor* processor = (nsIStyleRuleProcessor*)aProcessor; StatefulData* data = (StatefulData*)aData; - if (NS_OK == sheet->HasStateDependentStyle(data->mPresContext, data->mContent)) { + if (NS_OK == processor->HasStateDependentStyle(data->mPresContext, data->mMedium, + data->mContent)) { data->mStateful = PR_TRUE; return PR_FALSE; // stop iteration } @@ -830,17 +894,18 @@ NS_IMETHODIMP StyleSetImpl::HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent) { - StatefulData data(aPresContext, aContent); - if (mBackstopSheets) { - mBackstopSheets->EnumerateForwards(SheetHasStatefulStyle, &data); + if (! mRuleProcessors) { + GatherRuleProcessors(); } - if (mDocSheets && (! data.mStateful)) { - mDocSheets->EnumerateForwards(SheetHasStatefulStyle, &data); + if (mRuleProcessors) { + nsIAtom* medium = nsnull; + aPresContext->GetMedium(&medium); + StatefulData data(aPresContext, medium, aContent); + mRuleProcessors->EnumerateForwards(SheetHasStatefulStyle, &data); + NS_IF_RELEASE(medium); + return ((data.mStateful) ? NS_OK : NS_COMFALSE); } - if (mOverrideSheets && (! data.mStateful)) { - mOverrideSheets->EnumerateForwards(SheetHasStatefulStyle, &data); - } - return ((data.mStateful) ? NS_OK : NS_COMFALSE); + return NS_COMFALSE; }