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
This commit is contained in:
peterl%netscape.com
1999-10-08 03:09:31 +00:00
parent 12ad3a8ea1
commit d1916dab07
29 changed files with 1514 additions and 918 deletions

View File

@@ -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;
}