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
This commit is contained in:
parent
0b9d193a00
commit
c3453e4f35
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user