From c3453e4f3582f86646eafbb2a69fb8aebf42531c Mon Sep 17 00:00:00 2001 From: "peterl%netscape.com" Date: Tue, 15 Jun 1999 06:20:46 +0000 Subject: [PATCH] added faster medium testing support added default namespace support WIP for faster cascade git-svn-id: svn://10.0.0.236/trunk@35396 18797224-902f-48f8-a5cc-f745e15eee43 --- .../html/style/src/nsCSSStyleSheet.cpp | 262 ++++++++++++------ .../layout/html/style/src/nsCSSStyleSheet.cpp | 262 ++++++++++++------ mozilla/layout/style/nsCSSStyleSheet.cpp | 262 ++++++++++++------ 3 files changed, 552 insertions(+), 234 deletions(-) diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp index 44bf62d9800..38346f54218 100644 --- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp @@ -53,6 +53,7 @@ //#define DEBUG_REFS //#define DEBUG_RULES +#define DEBUG_CASCADE static NS_DEFINE_IID(kICSSStyleSheetIID, NS_ICSS_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); @@ -365,6 +366,7 @@ public: virtual void RemoveSheet(nsICSSStyleSheet* aParentSheet); virtual void ClearRuleCascades(void); + virtual void RebuildNameSpaces(void); nsVoidArray mSheets; @@ -374,6 +376,7 @@ public: nsHashtable* mMediumCascadeTable; nsINameSpace* mNameSpace; + PRInt32 mDefaultNameSpaceID; }; @@ -427,6 +430,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; + NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); @@ -470,6 +474,7 @@ public: NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const; NS_IMETHOD GetNameSpace(nsINameSpace*& aNameSpace) const; + NS_IMETHOD SetDefaultNameSpaceID(PRInt32 aDefaultNameSpaceID); NS_IMETHOD Clone(nsICSSStyleSheet*& aClone) const; @@ -509,6 +514,10 @@ protected: virtual ~CSSStyleSheetImpl(); void ClearRuleCascades(void); +#ifdef DEBUG_CASCADE + nsresult SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules); +#endif + nsresult GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules); nsresult CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules); RuleCascadeData* GetRuleCascade(nsIAtom* aMedium); @@ -836,7 +845,8 @@ CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet) mURL(nsnull), mOrderedRules(nsnull), mMediumCascadeTable(nsnull), - mNameSpace(nsnull) + mNameSpace(nsnull), + mDefaultNameSpaceID(kNameSpaceID_None) { mSheets.AppendElement(aParentSheet); } @@ -855,42 +865,13 @@ CloneRuleInto(nsISupports* aRule, void* aArray) return PR_TRUE; } -static PRBool -CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) -{ - nsICSSRule* rule = (nsICSSRule*)aRule; - PRInt32 type; - rule->GetType(type); - if (nsICSSRule::NAMESPACE_RULE == type) { - nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; - nsINameSpace** nameSpacePtr = (nsINameSpace**)aNameSpacePtr; - nsINameSpace* lastNameSpace = *nameSpacePtr; - nsINameSpace* newNameSpace; - - nsIAtom* prefix = nsnull; - nsAutoString urlSpec; - nameSpaceRule->GetPrefix(prefix); - nameSpaceRule->GetURLSpec(urlSpec); - lastNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); - NS_IF_RELEASE(prefix); - if (newNameSpace) { - NS_RELEASE(lastNameSpace); - (*nameSpacePtr) = newNameSpace; // takes ref - } - - return PR_TRUE; - } - // stop if not namespace, import or charset because namespace can't follow anything else - return (((nsICSSRule::CHARSET_RULE == type) || - (nsICSSRule::IMPORT_RULE)) ? PR_TRUE : PR_FALSE); -} - CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy, nsICSSStyleSheet* aParentSheet) : mSheets(), mURL(aCopy.mURL), mMediumCascadeTable(nsnull), - mNameSpace(nsnull) + mNameSpace(nsnull), + mDefaultNameSpaceID(aCopy.mDefaultNameSpaceID) { mSheets.AppendElement(aParentSheet); NS_IF_ADDREF(mURL); @@ -899,21 +880,12 @@ CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy, if (mOrderedRules) { aCopy.mOrderedRules->EnumerateForwards(CloneRuleInto, mOrderedRules); mOrderedRules->EnumerateForwards(SetStyleSheetReference, aParentSheet); - - if (aCopy.mNameSpace) { - nsINameSpaceManager* nameSpaceMgr; - NS_NewNameSpaceManager(&nameSpaceMgr); - if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mNameSpace); - NS_RELEASE(nameSpaceMgr); - mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); - } - } } } else { mOrderedRules = nsnull; } + RebuildNameSpaces(); } CSSStyleSheetInner::~CSSStyleSheetInner(void) @@ -924,6 +896,7 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void) NS_RELEASE(mOrderedRules); } ClearRuleCascades(); + NS_IF_RELEASE(mNameSpace); } CSSStyleSheetInner* @@ -976,6 +949,65 @@ CSSStyleSheetInner::ClearRuleCascades(void) } +static PRBool +CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) +{ + nsICSSRule* rule = (nsICSSRule*)aRule; + PRInt32 type; + rule->GetType(type); + if (nsICSSRule::NAMESPACE_RULE == type) { + nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; + nsINameSpace** nameSpacePtr = (nsINameSpace**)aNameSpacePtr; + nsINameSpace* lastNameSpace = *nameSpacePtr; + nsINameSpace* newNameSpace; + + nsIAtom* prefix = nsnull; + nsAutoString urlSpec; + nameSpaceRule->GetPrefix(prefix); + nameSpaceRule->GetURLSpec(urlSpec); + lastNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); + NS_IF_RELEASE(prefix); + if (newNameSpace) { + NS_RELEASE(lastNameSpace); + (*nameSpacePtr) = newNameSpace; // takes ref + } + + return PR_TRUE; + } + // stop if not namespace, import or charset because namespace can't follow anything else + return (((nsICSSRule::CHARSET_RULE == type) || + (nsICSSRule::IMPORT_RULE)) ? PR_TRUE : PR_FALSE); +} + +void +CSSStyleSheetInner::RebuildNameSpaces(void) +{ + nsINameSpaceManager* nameSpaceMgr; + if (mNameSpace) { + mNameSpace->GetNameSpaceManager(nameSpaceMgr); + NS_RELEASE(mNameSpace); + } + else { + NS_NewNameSpaceManager(&nameSpaceMgr); + } + if (nameSpaceMgr) { + nameSpaceMgr->CreateRootNameSpace(mNameSpace); + if (kNameSpaceID_Unknown != mDefaultNameSpaceID) { + nsINameSpace* defaultNameSpace; + mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, defaultNameSpace); + if (defaultNameSpace) { + NS_RELEASE(mNameSpace); + mNameSpace = defaultNameSpace; + } + } + NS_RELEASE(nameSpaceMgr); + if (mOrderedRules) { + mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); + } + } +} + + // ------------------------------- // CSS Style Sheet // @@ -1878,6 +1910,23 @@ CSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } +NS_IMETHODIMP +CSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const +{ + if (mMedia) { + if (-1 != mMedia->IndexOf(aMedium)) { + return NS_OK; + } + if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { + return NS_OK; + } + return NS_COMFALSE; + } + return NS_OK; +} + + + NS_IMETHODIMP CSSStyleSheetImpl::AppendMedium(nsIAtom* aMedium) { @@ -2051,19 +2100,7 @@ CSSStyleSheetImpl::PrependStyleRule(nsICSSRule* aRule) aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { // no api to prepend a namespace (ugh), release old ones and re-create them all - nsINameSpaceManager* nameSpaceMgr; - if (mInner->mNameSpace) { - mInner->mNameSpace->GetNameSpaceManager(nameSpaceMgr); - NS_RELEASE(mInner->mNameSpace); - } - else { - NS_NewNameSpaceManager(&nameSpaceMgr); - } - if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mInner->mNameSpace); - NS_RELEASE(nameSpaceMgr); - mInner->mOrderedRules->EnumerateForwards(CreateNameSpace, &(mInner->mNameSpace)); - } + mInner->RebuildNameSpaces(); } } } @@ -2155,6 +2192,16 @@ CSSStyleSheetImpl::GetNameSpace(nsINameSpace*& aNameSpace) const return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::SetDefaultNameSpaceID(PRInt32 aDefaultNameSpaceID) +{ + if (mInner) { + mInner->mDefaultNameSpaceID = aDefaultNameSpaceID; + mInner->RebuildNameSpaces(); + } + return NS_OK; +} + NS_IMETHODIMP CSSStyleSheetImpl::StyleSheetCount(PRInt32& aCount) const @@ -2416,6 +2463,49 @@ struct CascadeEnumData { nsISupportsArray* mRules; }; +static PRBool +GatherStyleRulesForMedium(nsISupports* aRule, void* aData) +{ + nsICSSRule* rule = (nsICSSRule*)aRule; + CascadeEnumData* data = (CascadeEnumData*)aData; + PRInt32 type; + rule->GetType(type); + + if (nsICSSRule::STYLE_RULE == type) { + nsICSSStyleRule* styleRule = (nsICSSStyleRule*)rule; + data->mRules->AppendElement(styleRule); + } + else if (nsICSSRule::MEDIA_RULE == type) { + nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; + if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { + mediaRule->EnumerateRulesForwards(GatherStyleRulesForMedium, aData); + } + } + return PR_TRUE; +} + +nsresult +CSSStyleSheetImpl::GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules) +{ + if (aRules) { + CSSStyleSheetImpl* child = mFirstChild; + while (nsnull != child) { + if (NS_OK == child->UseForMedium(aMedium)) { + child->GatherRulesFor(aMedium, aRules); + } + child = child->mNext; + } + + if (mInner && mInner->mOrderedRules) { + CascadeEnumData data(aMedium, aRules); + mInner->mOrderedRules->EnumerateForwards(GatherStyleRulesForMedium, &data); + } + } + return NS_OK; +} + +#ifdef DEBUG_CASCADE + struct WeightEnumData { WeightEnumData(PRInt32 aWeight) : mWeight(aWeight), @@ -2456,7 +2546,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } else if (nsICSSRule::MEDIA_RULE == type) { nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (NS_OK == mediaRule->HasMedium(data->mMedium)) { + if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } } @@ -2464,43 +2554,59 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } nsresult -CSSStyleSheetImpl::CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) +CSSStyleSheetImpl::SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) { if (aRules) { // get child rules first CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - PRBool mediumOK = PR_FALSE; - PRInt32 mediumCount; - child->GetMediumCount(mediumCount); - if (0 < mediumCount) { - PRInt32 index = 0; - nsIAtom* medium; - while ((PR_FALSE == mediumOK) && (index < mediumCount)) { - child->GetMediumAt(index++, medium); - if ((medium == nsLayoutAtoms::all) || (medium == aMedium)) { - mediumOK = PR_TRUE; - } - NS_RELEASE(medium); - } - } - else { - mediumOK = PR_TRUE; - } - if (mediumOK) { - child->CascadeRulesInto(aMedium, aRules); + if (NS_OK == child->UseForMedium(aMedium)) { + child->SlowCascadeRulesInto(aMedium, aRules); } child = child->mNext; } - + if (mInner && mInner->mOrderedRules) { CascadeEnumData data(aMedium, aRules); - // XXX much better to append and do non-destructive sort at end mInner->mOrderedRules->EnumerateForwards(InsertRuleByWeight, &data); } } return NS_OK; } +#endif + +static PRInt32 +CompareStyleRuleWeight(nsISupports* aRule1, nsISupports* aRule2, void* aData) +{ + nsICSSStyleRule* rule1 = (nsICSSStyleRule*)aRule1; + nsICSSStyleRule* rule2 = (nsICSSStyleRule*)aRule2; + return (rule2->GetWeight() - rule1->GetWeight()); +} + +nsresult +CSSStyleSheetImpl::CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) +{ +#ifdef FAST_CASCADE + if (aRules) { + GatherRulesFor(aMedium, aRules); + aRules->ShellSort(CompareStyleRuleWeight, nsnull); + +#ifdef DEBUG_CASCADE + nsISupportsArray* verifyArray = nsnull; + NS_NewISupportsArray(&verifyArray); + if (verifyArray) { + SlowCascadeRulesInto(aMedium, verifyArray); + NS_ASSERTION(verifyArray->Equals(aRules), "fast cascade failed"); + NS_RELEASE(verifyArray); + } +#endif + } + return NS_OK; +#else + return SlowCascadeRulesInto(aMedium, aRules); +#endif +} + RuleCascadeData* CSSStyleSheetImpl::GetRuleCascade(nsIAtom* aMedium) diff --git a/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp b/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp index 44bf62d9800..38346f54218 100644 --- a/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsCSSStyleSheet.cpp @@ -53,6 +53,7 @@ //#define DEBUG_REFS //#define DEBUG_RULES +#define DEBUG_CASCADE static NS_DEFINE_IID(kICSSStyleSheetIID, NS_ICSS_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); @@ -365,6 +366,7 @@ public: virtual void RemoveSheet(nsICSSStyleSheet* aParentSheet); virtual void ClearRuleCascades(void); + virtual void RebuildNameSpaces(void); nsVoidArray mSheets; @@ -374,6 +376,7 @@ public: nsHashtable* mMediumCascadeTable; nsINameSpace* mNameSpace; + PRInt32 mDefaultNameSpaceID; }; @@ -427,6 +430,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; + NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); @@ -470,6 +474,7 @@ public: NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const; NS_IMETHOD GetNameSpace(nsINameSpace*& aNameSpace) const; + NS_IMETHOD SetDefaultNameSpaceID(PRInt32 aDefaultNameSpaceID); NS_IMETHOD Clone(nsICSSStyleSheet*& aClone) const; @@ -509,6 +514,10 @@ protected: virtual ~CSSStyleSheetImpl(); void ClearRuleCascades(void); +#ifdef DEBUG_CASCADE + nsresult SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules); +#endif + nsresult GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules); nsresult CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules); RuleCascadeData* GetRuleCascade(nsIAtom* aMedium); @@ -836,7 +845,8 @@ CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet) mURL(nsnull), mOrderedRules(nsnull), mMediumCascadeTable(nsnull), - mNameSpace(nsnull) + mNameSpace(nsnull), + mDefaultNameSpaceID(kNameSpaceID_None) { mSheets.AppendElement(aParentSheet); } @@ -855,42 +865,13 @@ CloneRuleInto(nsISupports* aRule, void* aArray) return PR_TRUE; } -static PRBool -CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) -{ - nsICSSRule* rule = (nsICSSRule*)aRule; - PRInt32 type; - rule->GetType(type); - if (nsICSSRule::NAMESPACE_RULE == type) { - nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; - nsINameSpace** nameSpacePtr = (nsINameSpace**)aNameSpacePtr; - nsINameSpace* lastNameSpace = *nameSpacePtr; - nsINameSpace* newNameSpace; - - nsIAtom* prefix = nsnull; - nsAutoString urlSpec; - nameSpaceRule->GetPrefix(prefix); - nameSpaceRule->GetURLSpec(urlSpec); - lastNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); - NS_IF_RELEASE(prefix); - if (newNameSpace) { - NS_RELEASE(lastNameSpace); - (*nameSpacePtr) = newNameSpace; // takes ref - } - - return PR_TRUE; - } - // stop if not namespace, import or charset because namespace can't follow anything else - return (((nsICSSRule::CHARSET_RULE == type) || - (nsICSSRule::IMPORT_RULE)) ? PR_TRUE : PR_FALSE); -} - CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy, nsICSSStyleSheet* aParentSheet) : mSheets(), mURL(aCopy.mURL), mMediumCascadeTable(nsnull), - mNameSpace(nsnull) + mNameSpace(nsnull), + mDefaultNameSpaceID(aCopy.mDefaultNameSpaceID) { mSheets.AppendElement(aParentSheet); NS_IF_ADDREF(mURL); @@ -899,21 +880,12 @@ CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy, if (mOrderedRules) { aCopy.mOrderedRules->EnumerateForwards(CloneRuleInto, mOrderedRules); mOrderedRules->EnumerateForwards(SetStyleSheetReference, aParentSheet); - - if (aCopy.mNameSpace) { - nsINameSpaceManager* nameSpaceMgr; - NS_NewNameSpaceManager(&nameSpaceMgr); - if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mNameSpace); - NS_RELEASE(nameSpaceMgr); - mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); - } - } } } else { mOrderedRules = nsnull; } + RebuildNameSpaces(); } CSSStyleSheetInner::~CSSStyleSheetInner(void) @@ -924,6 +896,7 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void) NS_RELEASE(mOrderedRules); } ClearRuleCascades(); + NS_IF_RELEASE(mNameSpace); } CSSStyleSheetInner* @@ -976,6 +949,65 @@ CSSStyleSheetInner::ClearRuleCascades(void) } +static PRBool +CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) +{ + nsICSSRule* rule = (nsICSSRule*)aRule; + PRInt32 type; + rule->GetType(type); + if (nsICSSRule::NAMESPACE_RULE == type) { + nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; + nsINameSpace** nameSpacePtr = (nsINameSpace**)aNameSpacePtr; + nsINameSpace* lastNameSpace = *nameSpacePtr; + nsINameSpace* newNameSpace; + + nsIAtom* prefix = nsnull; + nsAutoString urlSpec; + nameSpaceRule->GetPrefix(prefix); + nameSpaceRule->GetURLSpec(urlSpec); + lastNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); + NS_IF_RELEASE(prefix); + if (newNameSpace) { + NS_RELEASE(lastNameSpace); + (*nameSpacePtr) = newNameSpace; // takes ref + } + + return PR_TRUE; + } + // stop if not namespace, import or charset because namespace can't follow anything else + return (((nsICSSRule::CHARSET_RULE == type) || + (nsICSSRule::IMPORT_RULE)) ? PR_TRUE : PR_FALSE); +} + +void +CSSStyleSheetInner::RebuildNameSpaces(void) +{ + nsINameSpaceManager* nameSpaceMgr; + if (mNameSpace) { + mNameSpace->GetNameSpaceManager(nameSpaceMgr); + NS_RELEASE(mNameSpace); + } + else { + NS_NewNameSpaceManager(&nameSpaceMgr); + } + if (nameSpaceMgr) { + nameSpaceMgr->CreateRootNameSpace(mNameSpace); + if (kNameSpaceID_Unknown != mDefaultNameSpaceID) { + nsINameSpace* defaultNameSpace; + mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, defaultNameSpace); + if (defaultNameSpace) { + NS_RELEASE(mNameSpace); + mNameSpace = defaultNameSpace; + } + } + NS_RELEASE(nameSpaceMgr); + if (mOrderedRules) { + mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); + } + } +} + + // ------------------------------- // CSS Style Sheet // @@ -1878,6 +1910,23 @@ CSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } +NS_IMETHODIMP +CSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const +{ + if (mMedia) { + if (-1 != mMedia->IndexOf(aMedium)) { + return NS_OK; + } + if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { + return NS_OK; + } + return NS_COMFALSE; + } + return NS_OK; +} + + + NS_IMETHODIMP CSSStyleSheetImpl::AppendMedium(nsIAtom* aMedium) { @@ -2051,19 +2100,7 @@ CSSStyleSheetImpl::PrependStyleRule(nsICSSRule* aRule) aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { // no api to prepend a namespace (ugh), release old ones and re-create them all - nsINameSpaceManager* nameSpaceMgr; - if (mInner->mNameSpace) { - mInner->mNameSpace->GetNameSpaceManager(nameSpaceMgr); - NS_RELEASE(mInner->mNameSpace); - } - else { - NS_NewNameSpaceManager(&nameSpaceMgr); - } - if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mInner->mNameSpace); - NS_RELEASE(nameSpaceMgr); - mInner->mOrderedRules->EnumerateForwards(CreateNameSpace, &(mInner->mNameSpace)); - } + mInner->RebuildNameSpaces(); } } } @@ -2155,6 +2192,16 @@ CSSStyleSheetImpl::GetNameSpace(nsINameSpace*& aNameSpace) const return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::SetDefaultNameSpaceID(PRInt32 aDefaultNameSpaceID) +{ + if (mInner) { + mInner->mDefaultNameSpaceID = aDefaultNameSpaceID; + mInner->RebuildNameSpaces(); + } + return NS_OK; +} + NS_IMETHODIMP CSSStyleSheetImpl::StyleSheetCount(PRInt32& aCount) const @@ -2416,6 +2463,49 @@ struct CascadeEnumData { nsISupportsArray* mRules; }; +static PRBool +GatherStyleRulesForMedium(nsISupports* aRule, void* aData) +{ + nsICSSRule* rule = (nsICSSRule*)aRule; + CascadeEnumData* data = (CascadeEnumData*)aData; + PRInt32 type; + rule->GetType(type); + + if (nsICSSRule::STYLE_RULE == type) { + nsICSSStyleRule* styleRule = (nsICSSStyleRule*)rule; + data->mRules->AppendElement(styleRule); + } + else if (nsICSSRule::MEDIA_RULE == type) { + nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; + if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { + mediaRule->EnumerateRulesForwards(GatherStyleRulesForMedium, aData); + } + } + return PR_TRUE; +} + +nsresult +CSSStyleSheetImpl::GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules) +{ + if (aRules) { + CSSStyleSheetImpl* child = mFirstChild; + while (nsnull != child) { + if (NS_OK == child->UseForMedium(aMedium)) { + child->GatherRulesFor(aMedium, aRules); + } + child = child->mNext; + } + + if (mInner && mInner->mOrderedRules) { + CascadeEnumData data(aMedium, aRules); + mInner->mOrderedRules->EnumerateForwards(GatherStyleRulesForMedium, &data); + } + } + return NS_OK; +} + +#ifdef DEBUG_CASCADE + struct WeightEnumData { WeightEnumData(PRInt32 aWeight) : mWeight(aWeight), @@ -2456,7 +2546,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } else if (nsICSSRule::MEDIA_RULE == type) { nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (NS_OK == mediaRule->HasMedium(data->mMedium)) { + if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } } @@ -2464,43 +2554,59 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } nsresult -CSSStyleSheetImpl::CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) +CSSStyleSheetImpl::SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) { if (aRules) { // get child rules first CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - PRBool mediumOK = PR_FALSE; - PRInt32 mediumCount; - child->GetMediumCount(mediumCount); - if (0 < mediumCount) { - PRInt32 index = 0; - nsIAtom* medium; - while ((PR_FALSE == mediumOK) && (index < mediumCount)) { - child->GetMediumAt(index++, medium); - if ((medium == nsLayoutAtoms::all) || (medium == aMedium)) { - mediumOK = PR_TRUE; - } - NS_RELEASE(medium); - } - } - else { - mediumOK = PR_TRUE; - } - if (mediumOK) { - child->CascadeRulesInto(aMedium, aRules); + if (NS_OK == child->UseForMedium(aMedium)) { + child->SlowCascadeRulesInto(aMedium, aRules); } child = child->mNext; } - + if (mInner && mInner->mOrderedRules) { CascadeEnumData data(aMedium, aRules); - // XXX much better to append and do non-destructive sort at end mInner->mOrderedRules->EnumerateForwards(InsertRuleByWeight, &data); } } return NS_OK; } +#endif + +static PRInt32 +CompareStyleRuleWeight(nsISupports* aRule1, nsISupports* aRule2, void* aData) +{ + nsICSSStyleRule* rule1 = (nsICSSStyleRule*)aRule1; + nsICSSStyleRule* rule2 = (nsICSSStyleRule*)aRule2; + return (rule2->GetWeight() - rule1->GetWeight()); +} + +nsresult +CSSStyleSheetImpl::CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) +{ +#ifdef FAST_CASCADE + if (aRules) { + GatherRulesFor(aMedium, aRules); + aRules->ShellSort(CompareStyleRuleWeight, nsnull); + +#ifdef DEBUG_CASCADE + nsISupportsArray* verifyArray = nsnull; + NS_NewISupportsArray(&verifyArray); + if (verifyArray) { + SlowCascadeRulesInto(aMedium, verifyArray); + NS_ASSERTION(verifyArray->Equals(aRules), "fast cascade failed"); + NS_RELEASE(verifyArray); + } +#endif + } + return NS_OK; +#else + return SlowCascadeRulesInto(aMedium, aRules); +#endif +} + RuleCascadeData* CSSStyleSheetImpl::GetRuleCascade(nsIAtom* aMedium) diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index 44bf62d9800..38346f54218 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -53,6 +53,7 @@ //#define DEBUG_REFS //#define DEBUG_RULES +#define DEBUG_CASCADE static NS_DEFINE_IID(kICSSStyleSheetIID, NS_ICSS_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); @@ -365,6 +366,7 @@ public: virtual void RemoveSheet(nsICSSStyleSheet* aParentSheet); virtual void ClearRuleCascades(void); + virtual void RebuildNameSpaces(void); nsVoidArray mSheets; @@ -374,6 +376,7 @@ public: nsHashtable* mMediumCascadeTable; nsINameSpace* mNameSpace; + PRInt32 mDefaultNameSpaceID; }; @@ -427,6 +430,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; + NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); @@ -470,6 +474,7 @@ public: NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const; NS_IMETHOD GetNameSpace(nsINameSpace*& aNameSpace) const; + NS_IMETHOD SetDefaultNameSpaceID(PRInt32 aDefaultNameSpaceID); NS_IMETHOD Clone(nsICSSStyleSheet*& aClone) const; @@ -509,6 +514,10 @@ protected: virtual ~CSSStyleSheetImpl(); void ClearRuleCascades(void); +#ifdef DEBUG_CASCADE + nsresult SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules); +#endif + nsresult GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules); nsresult CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules); RuleCascadeData* GetRuleCascade(nsIAtom* aMedium); @@ -836,7 +845,8 @@ CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet) mURL(nsnull), mOrderedRules(nsnull), mMediumCascadeTable(nsnull), - mNameSpace(nsnull) + mNameSpace(nsnull), + mDefaultNameSpaceID(kNameSpaceID_None) { mSheets.AppendElement(aParentSheet); } @@ -855,42 +865,13 @@ CloneRuleInto(nsISupports* aRule, void* aArray) return PR_TRUE; } -static PRBool -CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) -{ - nsICSSRule* rule = (nsICSSRule*)aRule; - PRInt32 type; - rule->GetType(type); - if (nsICSSRule::NAMESPACE_RULE == type) { - nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; - nsINameSpace** nameSpacePtr = (nsINameSpace**)aNameSpacePtr; - nsINameSpace* lastNameSpace = *nameSpacePtr; - nsINameSpace* newNameSpace; - - nsIAtom* prefix = nsnull; - nsAutoString urlSpec; - nameSpaceRule->GetPrefix(prefix); - nameSpaceRule->GetURLSpec(urlSpec); - lastNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); - NS_IF_RELEASE(prefix); - if (newNameSpace) { - NS_RELEASE(lastNameSpace); - (*nameSpacePtr) = newNameSpace; // takes ref - } - - return PR_TRUE; - } - // stop if not namespace, import or charset because namespace can't follow anything else - return (((nsICSSRule::CHARSET_RULE == type) || - (nsICSSRule::IMPORT_RULE)) ? PR_TRUE : PR_FALSE); -} - CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy, nsICSSStyleSheet* aParentSheet) : mSheets(), mURL(aCopy.mURL), mMediumCascadeTable(nsnull), - mNameSpace(nsnull) + mNameSpace(nsnull), + mDefaultNameSpaceID(aCopy.mDefaultNameSpaceID) { mSheets.AppendElement(aParentSheet); NS_IF_ADDREF(mURL); @@ -899,21 +880,12 @@ CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy, if (mOrderedRules) { aCopy.mOrderedRules->EnumerateForwards(CloneRuleInto, mOrderedRules); mOrderedRules->EnumerateForwards(SetStyleSheetReference, aParentSheet); - - if (aCopy.mNameSpace) { - nsINameSpaceManager* nameSpaceMgr; - NS_NewNameSpaceManager(&nameSpaceMgr); - if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mNameSpace); - NS_RELEASE(nameSpaceMgr); - mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); - } - } } } else { mOrderedRules = nsnull; } + RebuildNameSpaces(); } CSSStyleSheetInner::~CSSStyleSheetInner(void) @@ -924,6 +896,7 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void) NS_RELEASE(mOrderedRules); } ClearRuleCascades(); + NS_IF_RELEASE(mNameSpace); } CSSStyleSheetInner* @@ -976,6 +949,65 @@ CSSStyleSheetInner::ClearRuleCascades(void) } +static PRBool +CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) +{ + nsICSSRule* rule = (nsICSSRule*)aRule; + PRInt32 type; + rule->GetType(type); + if (nsICSSRule::NAMESPACE_RULE == type) { + nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; + nsINameSpace** nameSpacePtr = (nsINameSpace**)aNameSpacePtr; + nsINameSpace* lastNameSpace = *nameSpacePtr; + nsINameSpace* newNameSpace; + + nsIAtom* prefix = nsnull; + nsAutoString urlSpec; + nameSpaceRule->GetPrefix(prefix); + nameSpaceRule->GetURLSpec(urlSpec); + lastNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); + NS_IF_RELEASE(prefix); + if (newNameSpace) { + NS_RELEASE(lastNameSpace); + (*nameSpacePtr) = newNameSpace; // takes ref + } + + return PR_TRUE; + } + // stop if not namespace, import or charset because namespace can't follow anything else + return (((nsICSSRule::CHARSET_RULE == type) || + (nsICSSRule::IMPORT_RULE)) ? PR_TRUE : PR_FALSE); +} + +void +CSSStyleSheetInner::RebuildNameSpaces(void) +{ + nsINameSpaceManager* nameSpaceMgr; + if (mNameSpace) { + mNameSpace->GetNameSpaceManager(nameSpaceMgr); + NS_RELEASE(mNameSpace); + } + else { + NS_NewNameSpaceManager(&nameSpaceMgr); + } + if (nameSpaceMgr) { + nameSpaceMgr->CreateRootNameSpace(mNameSpace); + if (kNameSpaceID_Unknown != mDefaultNameSpaceID) { + nsINameSpace* defaultNameSpace; + mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, defaultNameSpace); + if (defaultNameSpace) { + NS_RELEASE(mNameSpace); + mNameSpace = defaultNameSpace; + } + } + NS_RELEASE(nameSpaceMgr); + if (mOrderedRules) { + mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); + } + } +} + + // ------------------------------- // CSS Style Sheet // @@ -1878,6 +1910,23 @@ CSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } +NS_IMETHODIMP +CSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const +{ + if (mMedia) { + if (-1 != mMedia->IndexOf(aMedium)) { + return NS_OK; + } + if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { + return NS_OK; + } + return NS_COMFALSE; + } + return NS_OK; +} + + + NS_IMETHODIMP CSSStyleSheetImpl::AppendMedium(nsIAtom* aMedium) { @@ -2051,19 +2100,7 @@ CSSStyleSheetImpl::PrependStyleRule(nsICSSRule* aRule) aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { // no api to prepend a namespace (ugh), release old ones and re-create them all - nsINameSpaceManager* nameSpaceMgr; - if (mInner->mNameSpace) { - mInner->mNameSpace->GetNameSpaceManager(nameSpaceMgr); - NS_RELEASE(mInner->mNameSpace); - } - else { - NS_NewNameSpaceManager(&nameSpaceMgr); - } - if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mInner->mNameSpace); - NS_RELEASE(nameSpaceMgr); - mInner->mOrderedRules->EnumerateForwards(CreateNameSpace, &(mInner->mNameSpace)); - } + mInner->RebuildNameSpaces(); } } } @@ -2155,6 +2192,16 @@ CSSStyleSheetImpl::GetNameSpace(nsINameSpace*& aNameSpace) const return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::SetDefaultNameSpaceID(PRInt32 aDefaultNameSpaceID) +{ + if (mInner) { + mInner->mDefaultNameSpaceID = aDefaultNameSpaceID; + mInner->RebuildNameSpaces(); + } + return NS_OK; +} + NS_IMETHODIMP CSSStyleSheetImpl::StyleSheetCount(PRInt32& aCount) const @@ -2416,6 +2463,49 @@ struct CascadeEnumData { nsISupportsArray* mRules; }; +static PRBool +GatherStyleRulesForMedium(nsISupports* aRule, void* aData) +{ + nsICSSRule* rule = (nsICSSRule*)aRule; + CascadeEnumData* data = (CascadeEnumData*)aData; + PRInt32 type; + rule->GetType(type); + + if (nsICSSRule::STYLE_RULE == type) { + nsICSSStyleRule* styleRule = (nsICSSStyleRule*)rule; + data->mRules->AppendElement(styleRule); + } + else if (nsICSSRule::MEDIA_RULE == type) { + nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; + if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { + mediaRule->EnumerateRulesForwards(GatherStyleRulesForMedium, aData); + } + } + return PR_TRUE; +} + +nsresult +CSSStyleSheetImpl::GatherRulesFor(nsIAtom* aMedium, nsISupportsArray* aRules) +{ + if (aRules) { + CSSStyleSheetImpl* child = mFirstChild; + while (nsnull != child) { + if (NS_OK == child->UseForMedium(aMedium)) { + child->GatherRulesFor(aMedium, aRules); + } + child = child->mNext; + } + + if (mInner && mInner->mOrderedRules) { + CascadeEnumData data(aMedium, aRules); + mInner->mOrderedRules->EnumerateForwards(GatherStyleRulesForMedium, &data); + } + } + return NS_OK; +} + +#ifdef DEBUG_CASCADE + struct WeightEnumData { WeightEnumData(PRInt32 aWeight) : mWeight(aWeight), @@ -2456,7 +2546,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } else if (nsICSSRule::MEDIA_RULE == type) { nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (NS_OK == mediaRule->HasMedium(data->mMedium)) { + if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } } @@ -2464,43 +2554,59 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } nsresult -CSSStyleSheetImpl::CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) +CSSStyleSheetImpl::SlowCascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) { if (aRules) { // get child rules first CSSStyleSheetImpl* child = mFirstChild; while (nsnull != child) { - PRBool mediumOK = PR_FALSE; - PRInt32 mediumCount; - child->GetMediumCount(mediumCount); - if (0 < mediumCount) { - PRInt32 index = 0; - nsIAtom* medium; - while ((PR_FALSE == mediumOK) && (index < mediumCount)) { - child->GetMediumAt(index++, medium); - if ((medium == nsLayoutAtoms::all) || (medium == aMedium)) { - mediumOK = PR_TRUE; - } - NS_RELEASE(medium); - } - } - else { - mediumOK = PR_TRUE; - } - if (mediumOK) { - child->CascadeRulesInto(aMedium, aRules); + if (NS_OK == child->UseForMedium(aMedium)) { + child->SlowCascadeRulesInto(aMedium, aRules); } child = child->mNext; } - + if (mInner && mInner->mOrderedRules) { CascadeEnumData data(aMedium, aRules); - // XXX much better to append and do non-destructive sort at end mInner->mOrderedRules->EnumerateForwards(InsertRuleByWeight, &data); } } return NS_OK; } +#endif + +static PRInt32 +CompareStyleRuleWeight(nsISupports* aRule1, nsISupports* aRule2, void* aData) +{ + nsICSSStyleRule* rule1 = (nsICSSStyleRule*)aRule1; + nsICSSStyleRule* rule2 = (nsICSSStyleRule*)aRule2; + return (rule2->GetWeight() - rule1->GetWeight()); +} + +nsresult +CSSStyleSheetImpl::CascadeRulesInto(nsIAtom* aMedium, nsISupportsArray* aRules) +{ +#ifdef FAST_CASCADE + if (aRules) { + GatherRulesFor(aMedium, aRules); + aRules->ShellSort(CompareStyleRuleWeight, nsnull); + +#ifdef DEBUG_CASCADE + nsISupportsArray* verifyArray = nsnull; + NS_NewISupportsArray(&verifyArray); + if (verifyArray) { + SlowCascadeRulesInto(aMedium, verifyArray); + NS_ASSERTION(verifyArray->Equals(aRules), "fast cascade failed"); + NS_RELEASE(verifyArray); + } +#endif + } + return NS_OK; +#else + return SlowCascadeRulesInto(aMedium, aRules); +#endif +} + RuleCascadeData* CSSStyleSheetImpl::GetRuleCascade(nsIAtom* aMedium)